Home | History | Annotate | Download | only in WebView
      1 /*
      2  * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
      3  * Copyright (C) 2006 David Smith (catfish.man (at) gmail.com)
      4  * Copyright (C) 2010 Igalia S.L
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  *
     10  * 1.  Redistributions of source code must retain the above copyright
     11  *     notice, this list of conditions and the following disclaimer.
     12  * 2.  Redistributions in binary form must reproduce the above copyright
     13  *     notice, this list of conditions and the following disclaimer in the
     14  *     documentation and/or other materials provided with the distribution.
     15  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
     16  *     its contributors may be used to endorse or promote products derived
     17  *     from this software without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
     20  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     22  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     23  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #import "WebViewInternal.h"
     32 #import "WebViewData.h"
     33 
     34 #import "DOMCSSStyleDeclarationInternal.h"
     35 #import "DOMNodeInternal.h"
     36 #import "DOMRangeInternal.h"
     37 #import "WebApplicationCache.h"
     38 #import "WebBackForwardListInternal.h"
     39 #import "WebBaseNetscapePluginView.h"
     40 #import "WebCache.h"
     41 #import "WebChromeClient.h"
     42 #import "WebContextMenuClient.h"
     43 #import "WebDOMOperationsPrivate.h"
     44 #import "WebDataSourceInternal.h"
     45 #import "WebDatabaseManagerInternal.h"
     46 #import "WebDefaultEditingDelegate.h"
     47 #import "WebDefaultPolicyDelegate.h"
     48 #import "WebDefaultUIDelegate.h"
     49 #import "WebDelegateImplementationCaching.h"
     50 #import "WebDeviceOrientationClient.h"
     51 #import "WebDeviceOrientationProvider.h"
     52 #import "WebDocument.h"
     53 #import "WebDocumentInternal.h"
     54 #import "WebDownload.h"
     55 #import "WebDownloadInternal.h"
     56 #import "WebDragClient.h"
     57 #import "WebDynamicScrollBarsViewInternal.h"
     58 #import "WebEditingDelegate.h"
     59 #import "WebEditorClient.h"
     60 #import "WebFormDelegatePrivate.h"
     61 #import "WebFrameInternal.h"
     62 #import "WebFrameViewInternal.h"
     63 #import "WebFullScreenController.h"
     64 #import "WebGeolocationClient.h"
     65 #import "WebGeolocationPositionInternal.h"
     66 #import "WebHTMLRepresentation.h"
     67 #import "WebHTMLViewInternal.h"
     68 #import "WebHistoryItemInternal.h"
     69 #import "WebIconDatabaseInternal.h"
     70 #import "WebInspector.h"
     71 #import "WebInspectorClient.h"
     72 #import "WebKitErrors.h"
     73 #import "WebKitLogging.h"
     74 #import "WebKitNSStringExtras.h"
     75 #import "WebKitStatisticsPrivate.h"
     76 #import "WebKitSystemBits.h"
     77 #import "WebKitVersionChecks.h"
     78 #import "WebLocalizableStrings.h"
     79 #import "WebNSDataExtras.h"
     80 #import "WebNSDataExtrasPrivate.h"
     81 #import "WebNSDictionaryExtras.h"
     82 #import "WebNSEventExtras.h"
     83 #import "WebNSObjectExtras.h"
     84 #import "WebNSPasteboardExtras.h"
     85 #import "WebNSPrintOperationExtras.h"
     86 #import "WebNSURLExtras.h"
     87 #import "WebNSURLRequestExtras.h"
     88 #import "WebNSViewExtras.h"
     89 #import "WebNodeHighlight.h"
     90 #import "WebPDFView.h"
     91 #import "WebPanelAuthenticationHandler.h"
     92 #import "WebPlatformStrategies.h"
     93 #import "WebPluginDatabase.h"
     94 #import "WebPluginHalterClient.h"
     95 #import "WebPolicyDelegate.h"
     96 #import "WebPreferenceKeysPrivate.h"
     97 #import "WebPreferencesPrivate.h"
     98 #import "WebScriptDebugDelegate.h"
     99 #import "WebScriptWorldInternal.h"
    100 #import "WebStorageManagerInternal.h"
    101 #import "WebSystemInterface.h"
    102 #import "WebTextCompletionController.h"
    103 #import "WebTextIterator.h"
    104 #import "WebUIDelegate.h"
    105 #import "WebUIDelegatePrivate.h"
    106 #import "WebVideoFullscreenController.h"
    107 #import <CoreFoundation/CFSet.h>
    108 #import <Foundation/NSURLConnection.h>
    109 #import <JavaScriptCore/APICast.h>
    110 #import <JavaScriptCore/JSValueRef.h>
    111 #import <WebCore/AbstractDatabase.h>
    112 #import <WebCore/ApplicationCacheStorage.h>
    113 #import <WebCore/BackForwardListImpl.h>
    114 #import <WebCore/MemoryCache.h>
    115 #import <WebCore/ColorMac.h>
    116 #import <WebCore/CSSComputedStyleDeclaration.h>
    117 #import <WebCore/Cursor.h>
    118 #import <WebCore/Document.h>
    119 #import <WebCore/DocumentLoader.h>
    120 #import <WebCore/DragController.h>
    121 #import <WebCore/DragData.h>
    122 #import <WebCore/Editor.h>
    123 #import <WebCore/EventHandler.h>
    124 #import <WebCore/ExceptionHandlers.h>
    125 #import <WebCore/FocusController.h>
    126 #import <WebCore/Frame.h>
    127 #import <WebCore/FrameLoader.h>
    128 #import <WebCore/FrameTree.h>
    129 #import <WebCore/FrameView.h>
    130 #import <WebCore/GCController.h>
    131 #import <WebCore/HTMLMediaElement.h>
    132 #import <WebCore/HTMLNames.h>
    133 #import <WebCore/HistoryItem.h>
    134 #import <WebCore/IconDatabase.h>
    135 #import <WebCore/JSCSSStyleDeclaration.h>
    136 #import <WebCore/JSDocument.h>
    137 #import <WebCore/JSElement.h>
    138 #import <WebCore/JSNodeList.h>
    139 #import <WebCore/Logging.h>
    140 #import <WebCore/MIMETypeRegistry.h>
    141 #import <WebCore/NodeList.h>
    142 #import <WebCore/Page.h>
    143 #import <WebCore/PageCache.h>
    144 #import <WebCore/PageGroup.h>
    145 #import <WebCore/PlatformMouseEvent.h>
    146 #import <WebCore/ProgressTracker.h>
    147 #import <WebCore/RenderView.h>
    148 #import <WebCore/RenderWidget.h>
    149 #import <WebCore/ResourceHandle.h>
    150 #import <WebCore/ResourceLoadScheduler.h>
    151 #import <WebCore/ResourceRequest.h>
    152 #import <WebCore/RuntimeApplicationChecks.h>
    153 #import <WebCore/SchemeRegistry.h>
    154 #import <WebCore/ScriptController.h>
    155 #import <WebCore/ScriptValue.h>
    156 #import <WebCore/SecurityOrigin.h>
    157 #import <WebCore/SelectionController.h>
    158 #import <WebCore/Settings.h>
    159 #import <WebCore/TextResourceDecoder.h>
    160 #import <WebCore/ThreadCheck.h>
    161 #import <WebCore/WebCoreObjCExtras.h>
    162 #import <WebCore/WebCoreView.h>
    163 #import <WebCore/Widget.h>
    164 #import <WebKit/DOM.h>
    165 #import <WebKit/DOMExtensions.h>
    166 #import <WebKit/DOMPrivate.h>
    167 #import <WebKitSystemInterface.h>
    168 #import <mach-o/dyld.h>
    169 #import <objc/objc-auto.h>
    170 #import <objc/objc-runtime.h>
    171 #import <runtime/ArrayPrototype.h>
    172 #import <runtime/DateInstance.h>
    173 #import <runtime/InitializeThreading.h>
    174 #import <runtime/JSLock.h>
    175 #import <runtime/JSValue.h>
    176 #import <wtf/Assertions.h>
    177 #import <wtf/HashTraits.h>
    178 #import <wtf/RefCountedLeakCounter.h>
    179 #import <wtf/RefPtr.h>
    180 #import <wtf/StdLibExtras.h>
    181 #import <wtf/Threading.h>
    182 
    183 #if ENABLE(DASHBOARD_SUPPORT)
    184 #import <WebKit/WebDashboardRegion.h>
    185 #endif
    186 
    187 #if ENABLE(CLIENT_BASED_GEOLOCATION)
    188 #import <WebCore/GeolocationController.h>
    189 #import <WebCore/GeolocationError.h>
    190 #endif
    191 
    192 #if ENABLE(GLIB_SUPPORT)
    193 #import <glib.h>
    194 #endif
    195 
    196 @interface NSSpellChecker (WebNSSpellCheckerDetails)
    197 - (void)_preflightChosenSpellServer;
    198 @end
    199 
    200 @interface NSView (WebNSViewDetails)
    201 - (NSView *)_hitTest:(NSPoint *)aPoint dragTypes:(NSSet *)types;
    202 - (void)_autoscrollForDraggingInfo:(id)dragInfo timeDelta:(NSTimeInterval)repeatDelta;
    203 - (BOOL)_shouldAutoscrollForDraggingInfo:(id)dragInfo;
    204 @end
    205 
    206 @interface NSWindow (WebNSWindowDetails)
    207 - (id)_oldFirstResponderBeforeBecoming;
    208 - (void)_enableScreenUpdatesIfNeeded;
    209 - (BOOL)_wrapsCarbonWindow;
    210 @end
    211 
    212 using namespace WebCore;
    213 using namespace JSC;
    214 
    215 #if defined(__ppc__) || defined(__ppc64__)
    216 #define PROCESSOR "PPC"
    217 #elif defined(__i386__) || defined(__x86_64__)
    218 #define PROCESSOR "Intel"
    219 #else
    220 #error Unknown architecture
    221 #endif
    222 
    223 #define FOR_EACH_RESPONDER_SELECTOR(macro) \
    224 macro(alignCenter) \
    225 macro(alignJustified) \
    226 macro(alignLeft) \
    227 macro(alignRight) \
    228 macro(capitalizeWord) \
    229 macro(centerSelectionInVisibleArea) \
    230 macro(changeAttributes) \
    231 macro(changeBaseWritingDirection) \
    232 macro(changeBaseWritingDirectionToLTR) \
    233 macro(changeBaseWritingDirectionToRTL) \
    234 macro(changeColor) \
    235 macro(changeDocumentBackgroundColor) \
    236 macro(changeFont) \
    237 macro(changeSpelling) \
    238 macro(checkSpelling) \
    239 macro(complete) \
    240 macro(copy) \
    241 macro(copyFont) \
    242 macro(cut) \
    243 macro(delete) \
    244 macro(deleteBackward) \
    245 macro(deleteBackwardByDecomposingPreviousCharacter) \
    246 macro(deleteForward) \
    247 macro(deleteToBeginningOfLine) \
    248 macro(deleteToBeginningOfParagraph) \
    249 macro(deleteToEndOfLine) \
    250 macro(deleteToEndOfParagraph) \
    251 macro(deleteToMark) \
    252 macro(deleteWordBackward) \
    253 macro(deleteWordForward) \
    254 macro(ignoreSpelling) \
    255 macro(indent) \
    256 macro(insertBacktab) \
    257 macro(insertLineBreak) \
    258 macro(insertNewline) \
    259 macro(insertNewlineIgnoringFieldEditor) \
    260 macro(insertParagraphSeparator) \
    261 macro(insertTab) \
    262 macro(insertTabIgnoringFieldEditor) \
    263 macro(lowercaseWord) \
    264 macro(makeBaseWritingDirectionLeftToRight) \
    265 macro(makeBaseWritingDirectionRightToLeft) \
    266 macro(makeTextWritingDirectionLeftToRight) \
    267 macro(makeTextWritingDirectionNatural) \
    268 macro(makeTextWritingDirectionRightToLeft) \
    269 macro(moveBackward) \
    270 macro(moveBackwardAndModifySelection) \
    271 macro(moveDown) \
    272 macro(moveDownAndModifySelection) \
    273 macro(moveForward) \
    274 macro(moveForwardAndModifySelection) \
    275 macro(moveLeft) \
    276 macro(moveLeftAndModifySelection) \
    277 macro(moveParagraphBackwardAndModifySelection) \
    278 macro(moveParagraphForwardAndModifySelection) \
    279 macro(moveRight) \
    280 macro(moveRightAndModifySelection) \
    281 macro(moveToBeginningOfDocument) \
    282 macro(moveToBeginningOfDocumentAndModifySelection) \
    283 macro(moveToBeginningOfLine) \
    284 macro(moveToBeginningOfLineAndModifySelection) \
    285 macro(moveToBeginningOfParagraph) \
    286 macro(moveToBeginningOfParagraphAndModifySelection) \
    287 macro(moveToBeginningOfSentence) \
    288 macro(moveToBeginningOfSentenceAndModifySelection) \
    289 macro(moveToEndOfDocument) \
    290 macro(moveToEndOfDocumentAndModifySelection) \
    291 macro(moveToEndOfLine) \
    292 macro(moveToEndOfLineAndModifySelection) \
    293 macro(moveToEndOfParagraph) \
    294 macro(moveToEndOfParagraphAndModifySelection) \
    295 macro(moveToEndOfSentence) \
    296 macro(moveToEndOfSentenceAndModifySelection) \
    297 macro(moveToLeftEndOfLine) \
    298 macro(moveToLeftEndOfLineAndModifySelection) \
    299 macro(moveToRightEndOfLine) \
    300 macro(moveToRightEndOfLineAndModifySelection) \
    301 macro(moveUp) \
    302 macro(moveUpAndModifySelection) \
    303 macro(moveWordBackward) \
    304 macro(moveWordBackwardAndModifySelection) \
    305 macro(moveWordForward) \
    306 macro(moveWordForwardAndModifySelection) \
    307 macro(moveWordLeft) \
    308 macro(moveWordLeftAndModifySelection) \
    309 macro(moveWordRight) \
    310 macro(moveWordRightAndModifySelection) \
    311 macro(outdent) \
    312 macro(orderFrontSubstitutionsPanel) \
    313 macro(pageDown) \
    314 macro(pageDownAndModifySelection) \
    315 macro(pageUp) \
    316 macro(pageUpAndModifySelection) \
    317 macro(paste) \
    318 macro(pasteAsPlainText) \
    319 macro(pasteAsRichText) \
    320 macro(pasteFont) \
    321 macro(performFindPanelAction) \
    322 macro(scrollLineDown) \
    323 macro(scrollLineUp) \
    324 macro(scrollPageDown) \
    325 macro(scrollPageUp) \
    326 macro(scrollToBeginningOfDocument) \
    327 macro(scrollToEndOfDocument) \
    328 macro(selectAll) \
    329 macro(selectLine) \
    330 macro(selectParagraph) \
    331 macro(selectSentence) \
    332 macro(selectToMark) \
    333 macro(selectWord) \
    334 macro(setMark) \
    335 macro(showGuessPanel) \
    336 macro(startSpeaking) \
    337 macro(stopSpeaking) \
    338 macro(subscript) \
    339 macro(superscript) \
    340 macro(swapWithMark) \
    341 macro(takeFindStringFromSelection) \
    342 macro(toggleBaseWritingDirection) \
    343 macro(transpose) \
    344 macro(underline) \
    345 macro(unscript) \
    346 macro(uppercaseWord) \
    347 macro(yank) \
    348 macro(yankAndSelect) \
    349 
    350 #define WebKitOriginalTopPrintingMarginKey @"WebKitOriginalTopMargin"
    351 #define WebKitOriginalBottomPrintingMarginKey @"WebKitOriginalBottomMargin"
    352 
    353 #define KeyboardUIModeDidChangeNotification @"com.apple.KeyboardUIModeDidChange"
    354 #define AppleKeyboardUIMode CFSTR("AppleKeyboardUIMode")
    355 #define UniversalAccessDomain CFSTR("com.apple.universalaccess")
    356 
    357 static BOOL s_didSetCacheModel;
    358 static WebCacheModel s_cacheModel = WebCacheModelDocumentViewer;
    359 
    360 #ifndef NDEBUG
    361 static const char webViewIsOpen[] = "At least one WebView is still open.";
    362 #endif
    363 
    364 @interface NSObject (WebValidateWithoutDelegate)
    365 - (BOOL)validateUserInterfaceItemWithoutDelegate:(id <NSValidatedUserInterfaceItem>)item;
    366 @end
    367 
    368 @interface _WebSafeForwarder : NSObject
    369 {
    370     id target; // Non-retained. Don't retain delegates.
    371     id defaultTarget;
    372     BOOL catchExceptions;
    373 }
    374 - (id)initWithTarget:(id)target defaultTarget:(id)defaultTarget catchExceptions:(BOOL)catchExceptions;
    375 @end
    376 
    377 @interface WebView (WebFileInternal)
    378 - (BOOL)_isLoading;
    379 - (WebFrameView *)_frameViewAtWindowPoint:(NSPoint)point;
    380 - (WebFrame *)_focusedFrame;
    381 + (void)_preflightSpellChecker;
    382 - (BOOL)_continuousCheckingAllowed;
    383 - (NSResponder *)_responderForResponderOperations;
    384 #if USE(ACCELERATED_COMPOSITING)
    385 - (void)_clearLayerSyncLoopObserver;
    386 #endif
    387 #if ENABLE(GLIB_SUPPORT)
    388 - (void)_clearGlibLoopObserver;
    389 #endif
    390 @end
    391 
    392 static void patchMailRemoveAttributesMethod();
    393 
    394 NSString *WebElementDOMNodeKey =            @"WebElementDOMNode";
    395 NSString *WebElementFrameKey =              @"WebElementFrame";
    396 NSString *WebElementImageKey =              @"WebElementImage";
    397 NSString *WebElementImageAltStringKey =     @"WebElementImageAltString";
    398 NSString *WebElementImageRectKey =          @"WebElementImageRect";
    399 NSString *WebElementImageURLKey =           @"WebElementImageURL";
    400 NSString *WebElementIsSelectedKey =         @"WebElementIsSelected";
    401 NSString *WebElementLinkLabelKey =          @"WebElementLinkLabel";
    402 NSString *WebElementLinkTargetFrameKey =    @"WebElementTargetFrame";
    403 NSString *WebElementLinkTitleKey =          @"WebElementLinkTitle";
    404 NSString *WebElementLinkURLKey =            @"WebElementLinkURL";
    405 NSString *WebElementMediaURLKey =           @"WebElementMediaURL";
    406 NSString *WebElementSpellingToolTipKey =    @"WebElementSpellingToolTip";
    407 NSString *WebElementTitleKey =              @"WebElementTitle";
    408 NSString *WebElementLinkIsLiveKey =         @"WebElementLinkIsLive";
    409 NSString *WebElementIsInScrollBarKey =      @"WebElementIsInScrollBar";
    410 NSString *WebElementIsContentEditableKey =  @"WebElementIsContentEditableKey";
    411 
    412 NSString *WebViewProgressStartedNotification =          @"WebProgressStartedNotification";
    413 NSString *WebViewProgressEstimateChangedNotification =  @"WebProgressEstimateChangedNotification";
    414 NSString *WebViewProgressFinishedNotification =         @"WebProgressFinishedNotification";
    415 
    416 NSString * const WebViewDidBeginEditingNotification =         @"WebViewDidBeginEditingNotification";
    417 NSString * const WebViewDidChangeNotification =               @"WebViewDidChangeNotification";
    418 NSString * const WebViewDidEndEditingNotification =           @"WebViewDidEndEditingNotification";
    419 NSString * const WebViewDidChangeTypingStyleNotification =    @"WebViewDidChangeTypingStyleNotification";
    420 NSString * const WebViewDidChangeSelectionNotification =      @"WebViewDidChangeSelectionNotification";
    421 
    422 enum { WebViewVersion = 4 };
    423 
    424 #define timedLayoutSize 4096
    425 
    426 static NSMutableSet *schemesWithRepresentationsSet;
    427 
    428 NSString *_WebCanGoBackKey =            @"canGoBack";
    429 NSString *_WebCanGoForwardKey =         @"canGoForward";
    430 NSString *_WebEstimatedProgressKey =    @"estimatedProgress";
    431 NSString *_WebIsLoadingKey =            @"isLoading";
    432 NSString *_WebMainFrameIconKey =        @"mainFrameIcon";
    433 NSString *_WebMainFrameTitleKey =       @"mainFrameTitle";
    434 NSString *_WebMainFrameURLKey =         @"mainFrameURL";
    435 NSString *_WebMainFrameDocumentKey =    @"mainFrameDocument";
    436 
    437 NSString *_WebViewDidStartAcceleratedCompositingNotification = @"_WebViewDidStartAcceleratedCompositing";
    438 
    439 @interface WebProgressItem : NSObject
    440 {
    441 @public
    442     long long bytesReceived;
    443     long long estimatedLength;
    444 }
    445 @end
    446 
    447 @implementation WebProgressItem
    448 @end
    449 
    450 static BOOL continuousSpellCheckingEnabled;
    451 #ifndef BUILDING_ON_TIGER
    452 static BOOL grammarCheckingEnabled;
    453 #endif
    454 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
    455 static BOOL automaticQuoteSubstitutionEnabled;
    456 static BOOL automaticLinkDetectionEnabled;
    457 static BOOL automaticDashSubstitutionEnabled;
    458 static BOOL automaticTextReplacementEnabled;
    459 static BOOL automaticSpellingCorrectionEnabled;
    460 #endif
    461 
    462 @implementation WebView (AllWebViews)
    463 
    464 static CFSetCallBacks NonRetainingSetCallbacks = {
    465     0,
    466     NULL,
    467     NULL,
    468     CFCopyDescription,
    469     CFEqual,
    470     CFHash
    471 };
    472 
    473 static CFMutableSetRef allWebViewsSet;
    474 
    475 + (void)_makeAllWebViewsPerformSelector:(SEL)selector
    476 {
    477     if (!allWebViewsSet)
    478         return;
    479 
    480     [(NSMutableSet *)allWebViewsSet makeObjectsPerformSelector:selector];
    481 }
    482 
    483 - (void)_removeFromAllWebViewsSet
    484 {
    485     if (allWebViewsSet)
    486         CFSetRemoveValue(allWebViewsSet, self);
    487 }
    488 
    489 - (void)_addToAllWebViewsSet
    490 {
    491     if (!allWebViewsSet)
    492         allWebViewsSet = CFSetCreateMutable(NULL, 0, &NonRetainingSetCallbacks);
    493 
    494     CFSetSetValue(allWebViewsSet, self);
    495 }
    496 
    497 @end
    498 
    499 @implementation WebView (WebPrivate)
    500 
    501 static inline int callGestalt(OSType selector)
    502 {
    503     SInt32 value = 0;
    504     Gestalt(selector, &value);
    505     return value;
    506 }
    507 
    508 // Uses underscores instead of dots because if "4." ever appears in a user agent string, old DHTML libraries treat it as Netscape 4.
    509 static NSString *createMacOSXVersionString()
    510 {
    511     // Can't use -[NSProcessInfo operatingSystemVersionString] because it has too much stuff we don't want.
    512     int major = callGestalt(gestaltSystemVersionMajor);
    513     ASSERT(major);
    514 
    515     int minor = callGestalt(gestaltSystemVersionMinor);
    516     int bugFix = callGestalt(gestaltSystemVersionBugFix);
    517     if (bugFix)
    518         return [[NSString alloc] initWithFormat:@"%d_%d_%d", major, minor, bugFix];
    519     if (minor)
    520         return [[NSString alloc] initWithFormat:@"%d_%d", major, minor];
    521     return [[NSString alloc] initWithFormat:@"%d", major];
    522 }
    523 
    524 static NSString *createUserVisibleWebKitVersionString()
    525 {
    526     // If the version is 4 digits long or longer, then the first digit represents
    527     // the version of the OS. Our user agent string should not include this first digit,
    528     // so strip it off and report the rest as the version. <rdar://problem/4997547>
    529     NSString *fullVersion = [[NSBundle bundleForClass:[WebView class]] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey];
    530     NSRange nonDigitRange = [fullVersion rangeOfCharacterFromSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]];
    531     if (nonDigitRange.location == NSNotFound && [fullVersion length] >= 4)
    532         return [[fullVersion substringFromIndex:1] copy];
    533     if (nonDigitRange.location != NSNotFound && nonDigitRange.location >= 4)
    534         return [[fullVersion substringFromIndex:1] copy];
    535     return [fullVersion copy];
    536 }
    537 
    538 + (NSString *)_standardUserAgentWithApplicationName:(NSString *)applicationName
    539 {
    540     // Note: Do *not* move the initialization of osVersion nor webKitVersion into the declaration.
    541     // Garbage collection won't correctly mark the global variable in that case <rdar://problem/5733674>.
    542     static NSString *osVersion;
    543     static NSString *webKitVersion;
    544     if (!osVersion)
    545         osVersion = createMacOSXVersionString();
    546     if (!webKitVersion)
    547         webKitVersion = createUserVisibleWebKitVersionString();
    548     if ([applicationName length])
    549         return [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; " PROCESSOR " Mac OS X %@) AppleWebKit/%@ (KHTML, like Gecko) %@", osVersion, webKitVersion, applicationName];
    550     return [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; " PROCESSOR " Mac OS X %@) AppleWebKit/%@ (KHTML, like Gecko)", osVersion, webKitVersion];
    551 }
    552 
    553 + (void)_reportException:(JSValueRef)exception inContext:(JSContextRef)context
    554 {
    555     if (!exception || !context)
    556         return;
    557 
    558     JSLock lock(SilenceAssertionsOnly);
    559     JSC::ExecState* execState = toJS(context);
    560 
    561     // Make sure the context has a DOMWindow global object, otherwise this context didn't originate from a WebView.
    562     if (!toJSDOMWindow(execState->lexicalGlobalObject()))
    563         return;
    564 
    565     reportException(execState, toJS(execState, exception));
    566 }
    567 
    568 static void WebKitInitializeApplicationCachePathIfNecessary()
    569 {
    570 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
    571     static BOOL initialized = NO;
    572     if (initialized)
    573         return;
    574 
    575     NSString *appName = [[NSBundle mainBundle] bundleIdentifier];
    576     if (!appName)
    577         appName = [[NSProcessInfo processInfo] processName];
    578 
    579     ASSERT(appName);
    580 
    581     NSString* cacheDir = [NSString _webkit_localCacheDirectoryWithBundleIdentifier:appName];
    582 
    583     cacheStorage().setCacheDirectory(cacheDir);
    584     initialized = YES;
    585 #endif
    586 }
    587 
    588 static bool runningLeopardMail()
    589 {
    590 #ifdef BUILDING_ON_LEOPARD
    591     return applicationIsAppleMail();
    592 #endif
    593     return NO;
    594 }
    595 
    596 static bool runningTigerMail()
    597 {
    598 #ifdef BUILDING_ON_TIGER
    599     return applicationIsAppleMail();
    600 #endif
    601     return NO;
    602 }
    603 
    604 static bool coreVideoHas7228836Fix()
    605 {
    606 #ifdef BUILDING_ON_LEOPARD
    607     NSBundle* coreVideoFrameworkBundle = [NSBundle bundleWithPath:@"/System/Library/Frameworks/CoreVideo.framework"];
    608     double version = [[coreVideoFrameworkBundle objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey] doubleValue];
    609     return (version >= 48);
    610 #endif
    611     return true;
    612 }
    613 
    614 static bool shouldEnableLoadDeferring()
    615 {
    616     return !applicationIsAdobeInstaller();
    617 }
    618 
    619 - (void)_dispatchPendingLoadRequests
    620 {
    621     resourceLoadScheduler()->servePendingRequests();
    622 }
    623 
    624 - (void)_registerDraggedTypes
    625 {
    626     NSArray *editableTypes = [WebHTMLView _insertablePasteboardTypes];
    627     NSArray *URLTypes = [NSPasteboard _web_dragTypesForURL];
    628     NSMutableSet *types = [[NSMutableSet alloc] initWithArray:editableTypes];
    629     [types addObjectsFromArray:URLTypes];
    630     [self registerForDraggedTypes:[types allObjects]];
    631     [types release];
    632 }
    633 
    634 - (BOOL)_usesDocumentViews
    635 {
    636     return _private->usesDocumentViews;
    637 }
    638 
    639 static NSString *leakMailQuirksUserScriptContents()
    640 {
    641     NSString *scriptPath = [[NSBundle bundleForClass:[WebView class]] pathForResource:@"MailQuirksUserScript" ofType:@"js"];
    642     NSStringEncoding encoding;
    643     return [[NSString alloc] initWithContentsOfFile:scriptPath usedEncoding:&encoding error:0];
    644 }
    645 
    646 - (void)_injectMailQuirksScript
    647 {
    648     static NSString *mailQuirksScriptContents = leakMailQuirksUserScriptContents();
    649     core(self)->group().addUserScriptToWorld(core([WebScriptWorld world]),
    650         mailQuirksScriptContents, KURL(), 0, 0, InjectAtDocumentEnd, InjectInAllFrames);
    651 }
    652 
    653 static bool needsOutlookQuirksScript()
    654 {
    655     static bool isOutlookNeedingQuirksScript = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_HTML5_PARSER)
    656         && applicationIsMicrosoftOutlook();
    657     return isOutlookNeedingQuirksScript;
    658 }
    659 
    660 static NSString *leakOutlookQuirksUserScriptContents()
    661 {
    662     NSString *scriptPath = [[NSBundle bundleForClass:[WebView class]] pathForResource:@"OutlookQuirksUserScript" ofType:@"js"];
    663     NSStringEncoding encoding;
    664     return [[NSString alloc] initWithContentsOfFile:scriptPath usedEncoding:&encoding error:0];
    665 }
    666 
    667 -(void)_injectOutlookQuirksScript
    668 {
    669     static NSString *outlookQuirksScriptContents = leakOutlookQuirksUserScriptContents();
    670     core(self)->group().addUserScriptToWorld(core([WebScriptWorld world]),
    671         outlookQuirksScriptContents, KURL(), 0, 0, InjectAtDocumentEnd, InjectInAllFrames);
    672 }
    673 
    674 - (void)_commonInitializationWithFrameName:(NSString *)frameName groupName:(NSString *)groupName usesDocumentViews:(BOOL)usesDocumentViews
    675 {
    676     WebCoreThreadViolationCheckRoundTwo();
    677 
    678 #ifndef NDEBUG
    679     WTF::RefCountedLeakCounter::suppressMessages(webViewIsOpen);
    680 #endif
    681 
    682     WebPreferences *standardPreferences = [WebPreferences standardPreferences];
    683     [standardPreferences willAddToWebView];
    684 
    685     _private->preferences = [standardPreferences retain];
    686     _private->catchesDelegateExceptions = YES;
    687     _private->mainFrameDocumentReady = NO;
    688     _private->drawsBackground = YES;
    689     _private->backgroundColor = [[NSColor colorWithDeviceWhite:1 alpha:1] retain];
    690     _private->usesDocumentViews = usesDocumentViews;
    691     _private->includesFlattenedCompositingLayersWhenDrawingToBitmap = YES;
    692 
    693     WebFrameView *frameView = nil;
    694     if (_private->usesDocumentViews) {
    695         NSRect f = [self frame];
    696         frameView = [[WebFrameView alloc] initWithFrame: NSMakeRect(0,0,f.size.width,f.size.height)];
    697         [frameView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
    698         [self addSubview:frameView];
    699         [frameView release];
    700     }
    701 
    702     static bool didOneTimeInitialization = false;
    703     if (!didOneTimeInitialization) {
    704         WebKitInitializeLoggingChannelsIfNecessary();
    705         WebCore::InitializeLoggingChannelsIfNecessary();
    706         [WebHistoryItem initWindowWatcherIfNecessary];
    707 #if ENABLE(DATABASE)
    708         WebKitInitializeDatabasesIfNecessary();
    709 #endif
    710 
    711 #if ENABLE(DOM_STORAGE)
    712         WebKitInitializeStorageIfNecessary();
    713 #endif
    714         WebKitInitializeApplicationCachePathIfNecessary();
    715         patchMailRemoveAttributesMethod();
    716 
    717         // Initialize our platform strategies.
    718         WebPlatformStrategies::initialize();
    719         Settings::setDefaultMinDOMTimerInterval(0.004);
    720 
    721         didOneTimeInitialization = true;
    722     }
    723 
    724     Page::PageClients pageClients;
    725     pageClients.chromeClient = new WebChromeClient(self);
    726     pageClients.contextMenuClient = new WebContextMenuClient(self);
    727     pageClients.editorClient = new WebEditorClient(self);
    728     pageClients.dragClient = new WebDragClient(self);
    729     pageClients.inspectorClient = new WebInspectorClient(self);
    730     pageClients.pluginHalterClient = new WebPluginHalterClient(self);
    731 #if ENABLE(CLIENT_BASED_GEOLOCATION)
    732     pageClients.geolocationClient = new WebGeolocationClient(self);
    733 #endif
    734 #if ENABLE(DEVICE_ORIENTATION)
    735     pageClients.deviceOrientationClient = new WebDeviceOrientationClient(self);
    736 #endif
    737     _private->page = new Page(pageClients);
    738 
    739     _private->page->setCanStartMedia([self window]);
    740     _private->page->settings()->setLocalStorageDatabasePath([[self preferences] _localStorageDatabasePath]);
    741 
    742     if (needsOutlookQuirksScript()) {
    743         _private->page->settings()->setShouldInjectUserScriptsInInitialEmptyDocument(true);
    744         [self _injectOutlookQuirksScript];
    745     }
    746 
    747     [WebFrame _createMainFrameWithPage:_private->page frameName:frameName frameView:frameView];
    748 
    749 #ifndef BUILDING_ON_TIGER
    750     NSRunLoop *runLoop = [NSRunLoop mainRunLoop];
    751 #else
    752     NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
    753 #endif
    754 
    755     if (WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_LOADING_DURING_COMMON_RUNLOOP_MODES))
    756         [self scheduleInRunLoop:runLoop forMode:(NSString *)kCFRunLoopCommonModes];
    757     else
    758         [self scheduleInRunLoop:runLoop forMode:NSDefaultRunLoopMode];
    759 
    760     [self _addToAllWebViewsSet];
    761     [self setGroupName:groupName];
    762 
    763     // If there's already a next key view (e.g., from a nib), wire it up to our
    764     // contained frame view. In any case, wire our next key view up to the our
    765     // contained frame view. This works together with our becomeFirstResponder
    766     // and setNextKeyView overrides.
    767     NSView *nextKeyView = [self nextKeyView];
    768     if (nextKeyView && nextKeyView != frameView)
    769         [frameView setNextKeyView:nextKeyView];
    770     [super setNextKeyView:frameView];
    771 
    772     if ([[self class] shouldIncludeInWebKitStatistics])
    773         ++WebViewCount;
    774 
    775     [self _registerDraggedTypes];
    776 
    777     WebPreferences *prefs = [self preferences];
    778     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:)
    779                                                  name:WebPreferencesChangedInternalNotification object:prefs];
    780 
    781     [self _preferencesChanged:[self preferences]];
    782     [[self preferences] _postPreferencesChangedAPINotification];
    783 
    784     if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_LOCAL_RESOURCE_SECURITY_RESTRICTION)) {
    785         // Originally, we allowed all local loads.
    786         SecurityOrigin::setLocalLoadPolicy(SecurityOrigin::AllowLocalLoadsForAll);
    787     } else if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_MORE_STRICT_LOCAL_RESOURCE_SECURITY_RESTRICTION)) {
    788         // Later, we allowed local loads for local URLs and documents loaded
    789         // with substitute data.
    790         SecurityOrigin::setLocalLoadPolicy(SecurityOrigin::AllowLocalLoadsForLocalAndSubstituteData);
    791     }
    792 
    793     if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_CONTENT_SNIFFING_FOR_FILE_URLS))
    794         ResourceHandle::forceContentSniffing();
    795 
    796 #if ENABLE(GLIB_SUPPORT)
    797     [self _scheduleGlibContextIterations];
    798 #endif
    799 
    800     if (runningTigerMail() || runningLeopardMail())
    801         [self _injectMailQuirksScript];
    802 }
    803 
    804 - (id)_initWithFrame:(NSRect)f frameName:(NSString *)frameName groupName:(NSString *)groupName usesDocumentViews:(BOOL)usesDocumentViews
    805 {
    806     self = [super initWithFrame:f];
    807     if (!self)
    808         return nil;
    809 
    810 #ifdef ENABLE_WEBKIT_UNSET_DYLD_FRAMEWORK_PATH
    811     // DYLD_FRAMEWORK_PATH is used so Safari will load the development version of WebKit, which
    812     // may not work with other WebKit applications.  Unsetting DYLD_FRAMEWORK_PATH removes the
    813     // need for Safari to unset it to prevent it from being passed to applications it launches.
    814     // Unsetting it when a WebView is first created is as good a place as any.
    815     // See <http://bugs.webkit.org/show_bug.cgi?id=4286> for more details.
    816     if (getenv("WEBKIT_UNSET_DYLD_FRAMEWORK_PATH")) {
    817         unsetenv("DYLD_FRAMEWORK_PATH");
    818         unsetenv("WEBKIT_UNSET_DYLD_FRAMEWORK_PATH");
    819     }
    820 #endif
    821 
    822     _private = [[WebViewPrivate alloc] init];
    823     [self _commonInitializationWithFrameName:frameName groupName:groupName usesDocumentViews:usesDocumentViews];
    824     [self setMaintainsBackForwardList: YES];
    825     return self;
    826 }
    827 
    828 - (BOOL)_mustDrawUnionedRect:(NSRect)rect singleRects:(const NSRect *)rects count:(NSInteger)count
    829 {
    830     // If count == 0 here, use the rect passed in for drawing. This is a workaround for:
    831     // <rdar://problem/3908282> REGRESSION (Mail): No drag image dragging selected text in Blot and Mail
    832     // The reason for the workaround is that this method is called explicitly from the code
    833     // to generate a drag image, and at that time, getRectsBeingDrawn:count: will return a zero count.
    834     const int cRectThreshold = 10;
    835     const float cWastedSpaceThreshold = 0.75f;
    836     BOOL useUnionedRect = (count <= 1) || (count > cRectThreshold);
    837     if (!useUnionedRect) {
    838         // Attempt to guess whether or not we should use the unioned rect or the individual rects.
    839         // We do this by computing the percentage of "wasted space" in the union.  If that wasted space
    840         // is too large, then we will do individual rect painting instead.
    841         float unionPixels = (rect.size.width * rect.size.height);
    842         float singlePixels = 0;
    843         for (int i = 0; i < count; ++i)
    844             singlePixels += rects[i].size.width * rects[i].size.height;
    845         float wastedSpace = 1 - (singlePixels / unionPixels);
    846         if (wastedSpace <= cWastedSpaceThreshold)
    847             useUnionedRect = YES;
    848     }
    849     return useUnionedRect;
    850 }
    851 
    852 - (void)drawSingleRect:(NSRect)rect
    853 {
    854     ASSERT(!_private->usesDocumentViews);
    855 
    856     [NSGraphicsContext saveGraphicsState];
    857     NSRectClip(rect);
    858 
    859     @try {
    860         [[self mainFrame] _drawRect:rect contentsOnly:NO];
    861 
    862         [[self _UIDelegateForwarder] webView:self didDrawRect:rect];
    863 
    864         if (WebNodeHighlight *currentHighlight = [self currentNodeHighlight])
    865             [currentHighlight setNeedsUpdateInTargetViewRect:rect];
    866 
    867         [NSGraphicsContext restoreGraphicsState];
    868     } @catch (NSException *localException) {
    869         [NSGraphicsContext restoreGraphicsState];
    870         LOG_ERROR("Exception caught while drawing: %@", localException);
    871         [localException raise];
    872     }
    873 }
    874 
    875 - (BOOL)isFlipped
    876 {
    877     return _private && !_private->usesDocumentViews;
    878 }
    879 
    880 - (void)setFrameSize:(NSSize)size
    881 {
    882     if (!_private->usesDocumentViews && !NSEqualSizes(_private->lastLayoutSize, size)) {
    883         Frame* frame = [self _mainCoreFrame];
    884         // FIXME: Viewless WebKit is broken with Safari banners (e.g., the Find banner).  We'll have to figure out a way for
    885         // Safari to communicate that this space is being consumed.  For WebKit with document views, there's no
    886         // need to do an explicit resize, since WebFrameViews have auto resizing turned on and will handle changing
    887         // their bounds automatically. See <rdar://problem/6835573> for details.
    888         frame->view()->resize(IntSize(size));
    889         frame->view()->setNeedsLayout();
    890         [self setNeedsDisplay:YES];
    891         _private->lastLayoutSize = size;
    892     }
    893 
    894     [super setFrameSize:size];
    895 }
    896 
    897 #if USE(ACCELERATED_COMPOSITING) || !defined(BUILDING_ON_TIGER)
    898 
    899 - (void)_viewWillDrawInternal
    900 {
    901     Frame* frame = [self _mainCoreFrame];
    902     if (frame && frame->view())
    903         frame->view()->updateLayoutAndStyleIfNeededRecursive();
    904 }
    905 
    906 #endif
    907 
    908 #ifndef BUILDING_ON_TIGER
    909 
    910 - (void)viewWillDraw
    911 {
    912     if (!_private->usesDocumentViews)
    913         [self _viewWillDrawInternal];
    914     [super viewWillDraw];
    915 }
    916 
    917 #endif
    918 
    919 
    920 - (void)drawRect:(NSRect)rect
    921 {
    922     if (_private->usesDocumentViews)
    923         return [super drawRect:rect];
    924 
    925     ASSERT_MAIN_THREAD();
    926 
    927     const NSRect *rects;
    928     NSInteger count;
    929     [self getRectsBeingDrawn:&rects count:&count];
    930 
    931 
    932     if ([self _mustDrawUnionedRect:rect singleRects:rects count:count])
    933         [self drawSingleRect:rect];
    934     else
    935         for (int i = 0; i < count; ++i)
    936             [self drawSingleRect:rects[i]];
    937 }
    938 
    939 + (NSArray *)_supportedMIMETypes
    940 {
    941     // Load the plug-in DB allowing plug-ins to install types.
    942     [WebPluginDatabase sharedDatabase];
    943     return [[WebFrameView _viewTypesAllowImageTypeOmission:NO] allKeys];
    944 }
    945 
    946 + (NSArray *)_supportedFileExtensions
    947 {
    948     NSMutableSet *extensions = [[NSMutableSet alloc] init];
    949     NSArray *MIMETypes = [self _supportedMIMETypes];
    950     NSEnumerator *enumerator = [MIMETypes objectEnumerator];
    951     NSString *MIMEType;
    952     while ((MIMEType = [enumerator nextObject]) != nil) {
    953         NSArray *extensionsForType = WKGetExtensionsForMIMEType(MIMEType);
    954         if (extensionsForType) {
    955             [extensions addObjectsFromArray:extensionsForType];
    956         }
    957     }
    958     NSArray *uniqueExtensions = [extensions allObjects];
    959     [extensions release];
    960     return uniqueExtensions;
    961 }
    962 
    963 static NSMutableSet *knownPluginMIMETypes()
    964 {
    965     static NSMutableSet *mimeTypes = [[NSMutableSet alloc] init];
    966 
    967     return mimeTypes;
    968 }
    969 
    970 + (void)_registerPluginMIMEType:(NSString *)MIMEType
    971 {
    972     [WebView registerViewClass:[WebHTMLView class] representationClass:[WebHTMLRepresentation class] forMIMEType:MIMEType];
    973     [knownPluginMIMETypes() addObject:MIMEType];
    974 }
    975 
    976 + (void)_unregisterPluginMIMEType:(NSString *)MIMEType
    977 {
    978     [self _unregisterViewClassAndRepresentationClassForMIMEType:MIMEType];
    979     [knownPluginMIMETypes() removeObject:MIMEType];
    980 }
    981 
    982 + (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType allowingPlugins:(BOOL)allowPlugins
    983 {
    984     MIMEType = [MIMEType lowercaseString];
    985     Class viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:YES] _webkit_objectForMIMEType:MIMEType];
    986     Class repClass = [[WebDataSource _repTypesAllowImageTypeOmission:YES] _webkit_objectForMIMEType:MIMEType];
    987 
    988     if (!viewClass || !repClass || [[WebPDFView supportedMIMETypes] containsObject:MIMEType]) {
    989         // Our optimization to avoid loading the plug-in DB and image types for the HTML case failed.
    990 
    991         if (allowPlugins) {
    992             // Load the plug-in DB allowing plug-ins to install types.
    993             [WebPluginDatabase sharedDatabase];
    994         }
    995 
    996         // Load the image types and get the view class and rep class. This should be the fullest picture of all handled types.
    997         viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:NO] _webkit_objectForMIMEType:MIMEType];
    998         repClass = [[WebDataSource _repTypesAllowImageTypeOmission:NO] _webkit_objectForMIMEType:MIMEType];
    999     }
   1000 
   1001     if (viewClass && repClass) {
   1002         if (viewClass == [WebHTMLView class] && repClass == [WebHTMLRepresentation class]) {
   1003             // Special-case WebHTMLView for text types that shouldn't be shown.
   1004             if ([[WebHTMLView unsupportedTextMIMETypes] containsObject:MIMEType])
   1005                 return NO;
   1006 
   1007             // If the MIME type is a known plug-in we might not want to load it.
   1008             if (!allowPlugins && [knownPluginMIMETypes() containsObject:MIMEType]) {
   1009                 BOOL isSupportedByWebKit = [[WebHTMLView supportedNonImageMIMETypes] containsObject:MIMEType] ||
   1010                     [[WebHTMLView supportedMIMETypes] containsObject:MIMEType];
   1011 
   1012                 // If this is a known plug-in MIME type and WebKit can't show it natively, we don't want to show it.
   1013                 if (!isSupportedByWebKit)
   1014                     return NO;
   1015             }
   1016         }
   1017         if (vClass)
   1018             *vClass = viewClass;
   1019         if (rClass)
   1020             *rClass = repClass;
   1021         return YES;
   1022     }
   1023 
   1024     return NO;
   1025 }
   1026 
   1027 - (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType
   1028 {
   1029     if ([[self class] _viewClass:vClass andRepresentationClass:rClass forMIMEType:MIMEType allowingPlugins:[_private->preferences arePlugInsEnabled]])
   1030         return YES;
   1031 
   1032     if (_private->pluginDatabase) {
   1033         WebBasePluginPackage *pluginPackage = [_private->pluginDatabase pluginForMIMEType:MIMEType];
   1034         if (pluginPackage) {
   1035             if (vClass)
   1036                 *vClass = [WebHTMLView class];
   1037             if (rClass)
   1038                 *rClass = [WebHTMLRepresentation class];
   1039             return YES;
   1040         }
   1041     }
   1042 
   1043     return NO;
   1044 }
   1045 
   1046 + (void)_setAlwaysUseATSU:(BOOL)f
   1047 {
   1048     [self _setAlwaysUsesComplexTextCodePath:f];
   1049 }
   1050 
   1051 + (void)_setAlwaysUsesComplexTextCodePath:(BOOL)f
   1052 {
   1053     Font::setCodePath(f ? Font::Complex : Font::Auto);
   1054 }
   1055 
   1056 + (BOOL)canCloseAllWebViews
   1057 {
   1058     return DOMWindow::dispatchAllPendingBeforeUnloadEvents();
   1059 }
   1060 
   1061 + (void)closeAllWebViews
   1062 {
   1063     DOMWindow::dispatchAllPendingUnloadEvents();
   1064 
   1065     // This will close the WebViews in a random order. Change this if close order is important.
   1066     // Make a new set to avoid mutating the set we are enumerating.
   1067     NSSet *webViewsToClose = [NSSet setWithSet:(NSSet *)allWebViewsSet];
   1068     NSEnumerator *enumerator = [webViewsToClose objectEnumerator];
   1069     while (WebView *webView = [enumerator nextObject])
   1070         [webView close];
   1071 }
   1072 
   1073 + (BOOL)canShowFile:(NSString *)path
   1074 {
   1075     return [[self class] canShowMIMEType:[WebView _MIMETypeForFile:path]];
   1076 }
   1077 
   1078 + (NSString *)suggestedFileExtensionForMIMEType:(NSString *)type
   1079 {
   1080     return WKGetPreferredExtensionForMIMEType(type);
   1081 }
   1082 
   1083 - (BOOL)_isClosed
   1084 {
   1085     return !_private || _private->closed;
   1086 }
   1087 
   1088 - (void)_closePluginDatabases
   1089 {
   1090     pluginDatabaseClientCount--;
   1091 
   1092     // Close both sets of plug-in databases because plug-ins need an opportunity to clean up files, etc.
   1093 
   1094     // Unload the WebView local plug-in database.
   1095     if (_private->pluginDatabase) {
   1096         [_private->pluginDatabase destroyAllPluginInstanceViews];
   1097         [_private->pluginDatabase close];
   1098         [_private->pluginDatabase release];
   1099         _private->pluginDatabase = nil;
   1100     }
   1101 
   1102     // Keep the global plug-in database active until the app terminates to avoid having to reload plug-in bundles.
   1103     if (!pluginDatabaseClientCount && applicationIsTerminating)
   1104         [WebPluginDatabase closeSharedDatabase];
   1105 }
   1106 
   1107 - (void)_closeWithFastTeardown
   1108 {
   1109 #ifndef NDEBUG
   1110     WTF::RefCountedLeakCounter::suppressMessages("At least one WebView was closed with fast teardown.");
   1111 #endif
   1112 
   1113     [[NSDistributedNotificationCenter defaultCenter] removeObserver:self];
   1114     [[NSNotificationCenter defaultCenter] removeObserver:self];
   1115 
   1116     [self _closePluginDatabases];
   1117 }
   1118 
   1119 static bool fastDocumentTeardownEnabled()
   1120 {
   1121 #ifdef NDEBUG
   1122     static bool enabled = ![[NSUserDefaults standardUserDefaults] boolForKey:WebKitEnableFullDocumentTeardownPreferenceKey];
   1123 #else
   1124     static bool initialized = false;
   1125     static bool enabled = false;
   1126     if (!initialized) {
   1127         // This allows debug builds to default to not have fast teardown, so leak checking still works.
   1128         // But still allow the WebKitEnableFullDocumentTeardown default to override it if present.
   1129         NSNumber *setting = [[NSUserDefaults standardUserDefaults] objectForKey:WebKitEnableFullDocumentTeardownPreferenceKey];
   1130         if (setting)
   1131             enabled = ![setting boolValue];
   1132         initialized = true;
   1133     }
   1134 #endif
   1135     return enabled;
   1136 }
   1137 
   1138 // _close is here only for backward compatibility; clients and subclasses should use
   1139 // public method -close instead.
   1140 - (void)_close
   1141 {
   1142     if (!_private || _private->closed)
   1143         return;
   1144 
   1145     _private->closed = YES;
   1146     [self _removeFromAllWebViewsSet];
   1147 
   1148     [self _closingEventHandling];
   1149 
   1150 #ifndef NDEBUG
   1151     WTF::RefCountedLeakCounter::cancelMessageSuppression(webViewIsOpen);
   1152 #endif
   1153 
   1154     // To quit the apps fast we skip document teardown, except plugins
   1155     // need to be destroyed and unloaded.
   1156     if (applicationIsTerminating && fastDocumentTeardownEnabled()) {
   1157         [self _closeWithFastTeardown];
   1158         return;
   1159     }
   1160 
   1161 #if ENABLE(VIDEO)
   1162     [self _exitFullscreen];
   1163 #endif
   1164 
   1165     if (Frame* mainFrame = [self _mainCoreFrame])
   1166         mainFrame->loader()->detachFromParent();
   1167 
   1168     [self setHostWindow:nil];
   1169 
   1170     [self setDownloadDelegate:nil];
   1171     [self setEditingDelegate:nil];
   1172     [self setFrameLoadDelegate:nil];
   1173     [self setPolicyDelegate:nil];
   1174     [self setResourceLoadDelegate:nil];
   1175     [self setScriptDebugDelegate:nil];
   1176     [self setUIDelegate:nil];
   1177 
   1178     [_private->inspector webViewClosed];
   1179 
   1180     // To avoid leaks, call removeDragCaret in case it wasn't called after moveDragCaretToPoint.
   1181     [self removeDragCaret];
   1182 
   1183     // Deleteing the WebCore::Page will clear the page cache so we call destroy on
   1184     // all the plug-ins in the page cache to break any retain cycles.
   1185     // See comment in HistoryItem::releaseAllPendingPageCaches() for more information.
   1186     Page* page = _private->page;
   1187     _private->page = 0;
   1188     delete page;
   1189 
   1190     if (_private->hasSpellCheckerDocumentTag) {
   1191         [[NSSpellChecker sharedSpellChecker] closeSpellDocumentWithTag:_private->spellCheckerDocumentTag];
   1192         _private->hasSpellCheckerDocumentTag = NO;
   1193     }
   1194 
   1195 #if USE(ACCELERATED_COMPOSITING)
   1196     [self _clearLayerSyncLoopObserver];
   1197 #endif
   1198 
   1199 #if ENABLE(GLIB_SUPPORT)
   1200     [self _clearGlibLoopObserver];
   1201 #endif
   1202 
   1203     [[NSDistributedNotificationCenter defaultCenter] removeObserver:self];
   1204     [[NSNotificationCenter defaultCenter] removeObserver:self];
   1205 
   1206     [WebPreferences _removeReferenceForIdentifier:[self preferencesIdentifier]];
   1207 
   1208     WebPreferences *preferences = _private->preferences;
   1209     _private->preferences = nil;
   1210     [preferences didRemoveFromWebView];
   1211     [preferences release];
   1212 
   1213     [self _closePluginDatabases];
   1214 
   1215 #ifndef NDEBUG
   1216     // Need this to make leak messages accurate.
   1217     if (applicationIsTerminating) {
   1218         gcController().garbageCollectNow();
   1219         [WebCache setDisabled:YES];
   1220     }
   1221 #endif
   1222 }
   1223 
   1224 // Indicates if the WebView is in the midst of a user gesture.
   1225 - (BOOL)_isProcessingUserGesture
   1226 {
   1227     WebFrame *frame = [self mainFrame];
   1228     return core(frame)->loader()->isProcessingUserGesture();
   1229 }
   1230 
   1231 + (NSString *)_MIMETypeForFile:(NSString *)path
   1232 {
   1233     NSString *extension = [path pathExtension];
   1234     NSString *MIMEType = nil;
   1235 
   1236     // Get the MIME type from the extension.
   1237     if ([extension length] != 0) {
   1238         MIMEType = WKGetMIMETypeForExtension(extension);
   1239     }
   1240 
   1241     // If we can't get a known MIME type from the extension, sniff.
   1242     if ([MIMEType length] == 0 || [MIMEType isEqualToString:@"application/octet-stream"]) {
   1243         NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:path];
   1244         NSData *data = [handle readDataOfLength:WEB_GUESS_MIME_TYPE_PEEK_LENGTH];
   1245         [handle closeFile];
   1246         if ([data length] != 0) {
   1247             MIMEType = [data _webkit_guessedMIMEType];
   1248         }
   1249         if ([MIMEType length] == 0) {
   1250             MIMEType = @"application/octet-stream";
   1251         }
   1252     }
   1253 
   1254     return MIMEType;
   1255 }
   1256 
   1257 - (WebDownload *)_downloadURL:(NSURL *)URL
   1258 {
   1259     ASSERT(URL);
   1260 
   1261     NSURLRequest *request = [[NSURLRequest alloc] initWithURL:URL];
   1262     WebDownload *download = [WebDownload _downloadWithRequest:request
   1263                                                      delegate:_private->downloadDelegate
   1264                                                     directory:nil];
   1265     [request release];
   1266 
   1267     return download;
   1268 }
   1269 
   1270 - (WebView *)_openNewWindowWithRequest:(NSURLRequest *)request
   1271 {
   1272     NSDictionary *features = [[NSDictionary alloc] init];
   1273     WebView *newWindowWebView = [[self _UIDelegateForwarder] webView:self
   1274                                             createWebViewWithRequest:nil
   1275                                                       windowFeatures:features];
   1276     [features release];
   1277     if (!newWindowWebView)
   1278         return nil;
   1279 
   1280     CallUIDelegate(newWindowWebView, @selector(webViewShow:));
   1281     return newWindowWebView;
   1282 }
   1283 
   1284 - (WebInspector *)inspector
   1285 {
   1286     if (!_private->inspector)
   1287         _private->inspector = [[WebInspector alloc] initWithWebView:self];
   1288     return _private->inspector;
   1289 }
   1290 
   1291 - (WebCore::Page*)page
   1292 {
   1293     return _private->page;
   1294 }
   1295 
   1296 - (NSMenu *)_menuForElement:(NSDictionary *)element defaultItems:(NSArray *)items
   1297 {
   1298     NSArray *defaultMenuItems = [[WebDefaultUIDelegate sharedUIDelegate] webView:self contextMenuItemsForElement:element defaultMenuItems:items];
   1299     NSArray *menuItems = defaultMenuItems;
   1300 
   1301     // CallUIDelegate returns nil if UIDelegate is nil or doesn't respond to the selector. So we need to check that here
   1302     // to distinguish between using defaultMenuItems or the delegate really returning nil to say "no context menu".
   1303     SEL selector = @selector(webView:contextMenuItemsForElement:defaultMenuItems:);
   1304     if (_private->UIDelegate && [_private->UIDelegate respondsToSelector:selector]) {
   1305         menuItems = CallUIDelegate(self, selector, element, defaultMenuItems);
   1306         if (!menuItems)
   1307             return nil;
   1308     }
   1309 
   1310     unsigned count = [menuItems count];
   1311     if (!count)
   1312         return nil;
   1313 
   1314     NSMenu *menu = [[NSMenu alloc] init];
   1315     for (unsigned i = 0; i < count; i++)
   1316         [menu addItem:[menuItems objectAtIndex:i]];
   1317 
   1318     return [menu autorelease];
   1319 }
   1320 
   1321 - (void)_mouseDidMoveOverElement:(NSDictionary *)dictionary modifierFlags:(NSUInteger)modifierFlags
   1322 {
   1323     // We originally intended to call this delegate method sometimes with a nil dictionary, but due to
   1324     // a bug dating back to WebKit 1.0 this delegate was never called with nil! Unfortunately we can't
   1325     // start calling this with nil since it will break Adobe Help Viewer, and possibly other clients.
   1326     if (!dictionary)
   1327         return;
   1328     CallUIDelegate(self, @selector(webView:mouseDidMoveOverElement:modifierFlags:), dictionary, modifierFlags);
   1329 }
   1330 
   1331 - (void)_loadBackForwardListFromOtherView:(WebView *)otherView
   1332 {
   1333     if (!_private->page)
   1334         return;
   1335 
   1336     if (!otherView->_private->page)
   1337         return;
   1338 
   1339     // It turns out the right combination of behavior is done with the back/forward load
   1340     // type.  (See behavior matrix at the top of WebFramePrivate.)  So we copy all the items
   1341     // in the back forward list, and go to the current one.
   1342 
   1343     BackForwardList* backForwardList = _private->page->backForwardList();
   1344     ASSERT(!backForwardList->currentItem()); // destination list should be empty
   1345 
   1346     BackForwardList* otherBackForwardList = otherView->_private->page->backForwardList();
   1347     if (!otherBackForwardList->currentItem())
   1348         return; // empty back forward list, bail
   1349 
   1350     HistoryItem* newItemToGoTo = 0;
   1351 
   1352     int lastItemIndex = otherBackForwardList->forwardListCount();
   1353     for (int i = -otherBackForwardList->backListCount(); i <= lastItemIndex; ++i) {
   1354         if (i == 0) {
   1355             // If this item is showing , save away its current scroll and form state,
   1356             // since that might have changed since loading and it is normally not saved
   1357             // until we leave that page.
   1358             otherView->_private->page->mainFrame()->loader()->history()->saveDocumentAndScrollState();
   1359         }
   1360         RefPtr<HistoryItem> newItem = otherBackForwardList->itemAtIndex(i)->copy();
   1361         if (i == 0)
   1362             newItemToGoTo = newItem.get();
   1363         backForwardList->addItem(newItem.release());
   1364     }
   1365 
   1366     ASSERT(newItemToGoTo);
   1367     _private->page->goToItem(newItemToGoTo, FrameLoadTypeIndexedBackForward);
   1368 }
   1369 
   1370 - (void)_setFormDelegate: (id<WebFormDelegate>)delegate
   1371 {
   1372     _private->formDelegate = delegate;
   1373 }
   1374 
   1375 - (id<WebFormDelegate>)_formDelegate
   1376 {
   1377     return _private->formDelegate;
   1378 }
   1379 
   1380 - (BOOL)_needsAdobeFrameReloadingQuirk
   1381 {
   1382     static BOOL needsQuirk = WKAppVersionCheckLessThan(@"com.adobe.Acrobat", -1, 9.0)
   1383         || WKAppVersionCheckLessThan(@"com.adobe.Acrobat.Pro", -1, 9.0)
   1384         || WKAppVersionCheckLessThan(@"com.adobe.Reader", -1, 9.0)
   1385         || WKAppVersionCheckLessThan(@"com.adobe.distiller", -1, 9.0)
   1386         || WKAppVersionCheckLessThan(@"com.adobe.Contribute", -1, 4.2)
   1387         || WKAppVersionCheckLessThan(@"com.adobe.dreamweaver-9.0", -1, 9.1)
   1388         || WKAppVersionCheckLessThan(@"com.macromedia.fireworks", -1, 9.1)
   1389         || WKAppVersionCheckLessThan(@"com.adobe.InCopy", -1, 5.1)
   1390         || WKAppVersionCheckLessThan(@"com.adobe.InDesign", -1, 5.1)
   1391         || WKAppVersionCheckLessThan(@"com.adobe.Soundbooth", -1, 2);
   1392 
   1393     return needsQuirk;
   1394 }
   1395 
   1396 - (BOOL)_needsLinkElementTextCSSQuirk
   1397 {
   1398     static BOOL needsQuirk = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_LINK_ELEMENT_TEXT_CSS_QUIRK)
   1399         && WKAppVersionCheckLessThan(@"com.e-frontier.shade10", -1, 10.6);
   1400     return needsQuirk;
   1401 }
   1402 
   1403 - (BOOL)_needsKeyboardEventDisambiguationQuirks
   1404 {
   1405     static BOOL needsQuirks = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_IE_COMPATIBLE_KEYBOARD_EVENT_DISPATCH) && !applicationIsSafari();
   1406     return needsQuirks;
   1407 }
   1408 
   1409 - (BOOL)_needsFrameLoadDelegateRetainQuirk
   1410 {
   1411     static BOOL needsQuirk = WKAppVersionCheckLessThan(@"com.equinux.iSale5", -1, 5.6);
   1412     return needsQuirk;
   1413 }
   1414 
   1415 
   1416 - (BOOL)_needsPreHTML5ParserQuirks
   1417 {
   1418     // AOL Instant Messenger and Microsoft My Day contain markup incompatible
   1419     // with the new HTML5 parser. If these applications were linked against a
   1420     // version of WebKit prior to the introduction of the HTML5 parser, enable
   1421     // parser quirks to maintain compatibility. For details, see
   1422     // <https://bugs.webkit.org/show_bug.cgi?id=46134> and
   1423     // <https://bugs.webkit.org/show_bug.cgi?id=46334>.
   1424     static bool isApplicationNeedingParserQuirks = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_HTML5_PARSER)
   1425         && (applicationIsAOLInstantMessenger() || applicationIsMicrosoftMyDay());
   1426 
   1427     // Mail.app must continue to display HTML email that contains quirky markup.
   1428     static bool isAppleMail = applicationIsAppleMail();
   1429 
   1430     return isApplicationNeedingParserQuirks
   1431         || isAppleMail
   1432 #if ENABLE(DASHBOARD_SUPPORT)
   1433         // Pre-HTML5 parser quirks are required to remain compatible with many
   1434         // Dashboard widgets. See <rdar://problem/8175982>.
   1435         || (_private->page && _private->page->settings()->usesDashboardBackwardCompatibilityMode())
   1436 #endif
   1437         || [[self preferences] usePreHTML5ParserQuirks];
   1438 }
   1439 
   1440 - (BOOL)_needsUnrestrictedGetMatchedCSSRules
   1441 {
   1442     static bool needsUnrestrictedGetMatchedCSSRules = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_GET_MATCHED_CSS_RULES_RESTRICTIONS) && applicationIsSafari();
   1443     return needsUnrestrictedGetMatchedCSSRules;
   1444 }
   1445 
   1446 - (void)_preferencesChangedNotification:(NSNotification *)notification
   1447 {
   1448     WebPreferences *preferences = (WebPreferences *)[notification object];
   1449     [self _preferencesChanged:preferences];
   1450 }
   1451 
   1452 - (void)_preferencesChanged:(WebPreferences *)preferences
   1453 {
   1454     ASSERT(preferences == [self preferences]);
   1455     if (!_private->userAgentOverridden)
   1456         _private->userAgent = String();
   1457 
   1458     // Cache this value so we don't have to read NSUserDefaults on each page load
   1459     _private->useSiteSpecificSpoofing = [preferences _useSiteSpecificSpoofing];
   1460 
   1461     // Update corresponding WebCore Settings object.
   1462     if (!_private->page)
   1463         return;
   1464 
   1465     Settings* settings = _private->page->settings();
   1466 
   1467     settings->setCursiveFontFamily([preferences cursiveFontFamily]);
   1468     settings->setDefaultFixedFontSize([preferences defaultFixedFontSize]);
   1469     settings->setDefaultFontSize([preferences defaultFontSize]);
   1470     settings->setDefaultTextEncodingName([preferences defaultTextEncodingName]);
   1471     settings->setUsesEncodingDetector([preferences usesEncodingDetector]);
   1472     settings->setFantasyFontFamily([preferences fantasyFontFamily]);
   1473     settings->setFixedFontFamily([preferences fixedFontFamily]);
   1474     settings->setForceFTPDirectoryListings([preferences _forceFTPDirectoryListings]);
   1475     settings->setFTPDirectoryTemplatePath([preferences _ftpDirectoryTemplatePath]);
   1476     settings->setLocalStorageDatabasePath([preferences _localStorageDatabasePath]);
   1477     settings->setJavaEnabled([preferences isJavaEnabled]);
   1478     settings->setJavaScriptEnabled([preferences isJavaScriptEnabled]);
   1479     settings->setWebSecurityEnabled([preferences isWebSecurityEnabled]);
   1480     settings->setAllowUniversalAccessFromFileURLs([preferences allowUniversalAccessFromFileURLs]);
   1481     settings->setAllowFileAccessFromFileURLs([preferences allowFileAccessFromFileURLs]);
   1482     settings->setJavaScriptCanOpenWindowsAutomatically([preferences javaScriptCanOpenWindowsAutomatically]);
   1483     settings->setMinimumFontSize([preferences minimumFontSize]);
   1484     settings->setMinimumLogicalFontSize([preferences minimumLogicalFontSize]);
   1485     settings->setPluginsEnabled([preferences arePlugInsEnabled]);
   1486 #if ENABLE(DATABASE)
   1487     AbstractDatabase::setIsAvailable([preferences databasesEnabled]);
   1488 #endif
   1489     settings->setLocalStorageEnabled([preferences localStorageEnabled]);
   1490     settings->setExperimentalNotificationsEnabled([preferences experimentalNotificationsEnabled]);
   1491     settings->setPrivateBrowsingEnabled([preferences privateBrowsingEnabled]);
   1492     settings->setSansSerifFontFamily([preferences sansSerifFontFamily]);
   1493     settings->setSerifFontFamily([preferences serifFontFamily]);
   1494     settings->setStandardFontFamily([preferences standardFontFamily]);
   1495     settings->setLoadsImagesAutomatically([preferences loadsImagesAutomatically]);
   1496     settings->setLoadsSiteIconsIgnoringImageLoadingSetting([preferences loadsSiteIconsIgnoringImageLoadingPreference]);
   1497     settings->setShouldPrintBackgrounds([preferences shouldPrintBackgrounds]);
   1498     settings->setTextAreasAreResizable([preferences textAreasAreResizable]);
   1499     settings->setShrinksStandaloneImagesToFit([preferences shrinksStandaloneImagesToFit]);
   1500     settings->setEditableLinkBehavior(core([preferences editableLinkBehavior]));
   1501     settings->setEditingBehaviorType(core([preferences editingBehavior]));
   1502     settings->setTextDirectionSubmenuInclusionBehavior(core([preferences textDirectionSubmenuInclusionBehavior]));
   1503     settings->setDOMPasteAllowed([preferences isDOMPasteAllowed]);
   1504     settings->setUsesPageCache([self usesPageCache]);
   1505     settings->setShowsURLsInToolTips([preferences showsURLsInToolTips]);
   1506     settings->setDeveloperExtrasEnabled([preferences developerExtrasEnabled]);
   1507     settings->setAuthorAndUserStylesEnabled([preferences authorAndUserStylesEnabled]);
   1508     settings->setApplicationChromeMode([preferences applicationChromeModeEnabled]);
   1509     if ([preferences userStyleSheetEnabled]) {
   1510         NSString* location = [[preferences userStyleSheetLocation] _web_originalDataAsString];
   1511         if ([location isEqualToString:@"apple-dashboard://stylesheet"])
   1512             location = @"file:///System/Library/PrivateFrameworks/DashboardClient.framework/Resources/widget.css";
   1513         settings->setUserStyleSheetLocation([NSURL URLWithString:(location ? location : @"")]);
   1514     } else
   1515         settings->setUserStyleSheetLocation([NSURL URLWithString:@""]);
   1516     settings->setNeedsAdobeFrameReloadingQuirk([self _needsAdobeFrameReloadingQuirk]);
   1517     settings->setTreatsAnyTextCSSLinkAsStylesheet([self _needsLinkElementTextCSSQuirk]);
   1518     settings->setNeedsKeyboardEventDisambiguationQuirks([self _needsKeyboardEventDisambiguationQuirks]);
   1519     settings->setNeedsLeopardMailQuirks(runningLeopardMail());
   1520     settings->setNeedsTigerMailQuirks(runningTigerMail());
   1521     settings->setNeedsSiteSpecificQuirks(_private->useSiteSpecificSpoofing);
   1522     settings->setWebArchiveDebugModeEnabled([preferences webArchiveDebugModeEnabled]);
   1523     settings->setLocalFileContentSniffingEnabled([preferences localFileContentSniffingEnabled]);
   1524     settings->setOfflineWebApplicationCacheEnabled([preferences offlineWebApplicationCacheEnabled]);
   1525     settings->setJavaScriptCanAccessClipboard([preferences javaScriptCanAccessClipboard]);
   1526     settings->setXSSAuditorEnabled([preferences isXSSAuditorEnabled]);
   1527     settings->setEnforceCSSMIMETypeInNoQuirksMode(!WKAppVersionCheckLessThan(@"com.apple.iWeb", -1, 2.1));
   1528     settings->setDNSPrefetchingEnabled([preferences isDNSPrefetchingEnabled]);
   1529 
   1530     // FIXME: Enabling accelerated compositing when WebGL is enabled causes tests to fail on Leopard which expect HW compositing to be disabled.
   1531     // Until we fix that, I will comment out the test (CFM)
   1532     settings->setAcceleratedCompositingEnabled((coreVideoHas7228836Fix() || [preferences webGLEnabled] ||
   1533         [preferences accelerated2dCanvasEnabled]) && [preferences acceleratedCompositingEnabled]);
   1534     settings->setAcceleratedDrawingEnabled([preferences acceleratedDrawingEnabled]);
   1535     settings->setCanvasUsesAcceleratedDrawing([preferences canvasUsesAcceleratedDrawing]);
   1536     settings->setShowDebugBorders([preferences showDebugBorders]);
   1537     settings->setShowRepaintCounter([preferences showRepaintCounter]);
   1538     settings->setPluginAllowedRunTime([preferences pluginAllowedRunTime]);
   1539     settings->setWebAudioEnabled([preferences webAudioEnabled]);
   1540     settings->setWebGLEnabled([preferences webGLEnabled]);
   1541     settings->setAccelerated2dCanvasEnabled([preferences accelerated2dCanvasEnabled]);
   1542     settings->setLoadDeferringEnabled(shouldEnableLoadDeferring());
   1543     settings->setFrameFlatteningEnabled([preferences isFrameFlatteningEnabled]);
   1544     settings->setSpatialNavigationEnabled([preferences isSpatialNavigationEnabled]);
   1545     settings->setPaginateDuringLayoutEnabled([preferences paginateDuringLayoutEnabled]);
   1546 #if ENABLE(FULLSCREEN_API)
   1547     settings->setFullScreenEnabled([preferences fullScreenEnabled]);
   1548 #endif
   1549 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
   1550     // Asynchronous spell checking API is available for 10.6 or later.
   1551     settings->setAsynchronousSpellCheckingEnabled([preferences asynchronousSpellCheckingEnabled]);
   1552 #endif
   1553     settings->setMemoryInfoEnabled([preferences memoryInfoEnabled]);
   1554     settings->setHyperlinkAuditingEnabled([preferences hyperlinkAuditingEnabled]);
   1555     settings->setUsePreHTML5ParserQuirks([self _needsPreHTML5ParserQuirks]);
   1556     settings->setUseQuickLookResourceCachingQuirks([preferences useQuickLookResourceCachingQuirks]);
   1557     settings->setCrossOriginCheckInGetMatchedCSSRulesDisabled([self _needsUnrestrictedGetMatchedCSSRules]);
   1558     settings->setInteractiveFormValidationEnabled([self interactiveFormValidationEnabled]);
   1559     settings->setValidationMessageTimerMagnification([self validationMessageTimerMagnification]);
   1560 
   1561     // Application Cache Preferences are stored on the global cache storage manager, not in Settings.
   1562     [WebApplicationCache setDefaultOriginQuota:[preferences applicationCacheDefaultOriginQuota]];
   1563 
   1564     BOOL zoomsTextOnly = [preferences zoomsTextOnly];
   1565     if (_private->zoomsTextOnly != zoomsTextOnly)
   1566         [self _setZoomMultiplier:_private->zoomMultiplier isTextOnly:zoomsTextOnly];
   1567 }
   1568 
   1569 static inline IMP getMethod(id o, SEL s)
   1570 {
   1571     return [o respondsToSelector:s] ? [o methodForSelector:s] : 0;
   1572 }
   1573 
   1574 - (void)_cacheResourceLoadDelegateImplementations
   1575 {
   1576     WebResourceDelegateImplementationCache *cache = &_private->resourceLoadDelegateImplementations;
   1577     id delegate = _private->resourceProgressDelegate;
   1578 
   1579     if (!delegate) {
   1580         bzero(cache, sizeof(WebResourceDelegateImplementationCache));
   1581         return;
   1582     }
   1583 
   1584     cache->didCancelAuthenticationChallengeFunc = getMethod(delegate, @selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:));
   1585     cache->didFailLoadingWithErrorFromDataSourceFunc = getMethod(delegate, @selector(webView:resource:didFailLoadingWithError:fromDataSource:));
   1586     cache->didFinishLoadingFromDataSourceFunc = getMethod(delegate, @selector(webView:resource:didFinishLoadingFromDataSource:));
   1587     cache->didLoadResourceFromMemoryCacheFunc = getMethod(delegate, @selector(webView:didLoadResourceFromMemoryCache:response:length:fromDataSource:));
   1588     cache->didReceiveAuthenticationChallengeFunc = getMethod(delegate, @selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:));
   1589 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
   1590     cache->canAuthenticateAgainstProtectionSpaceFunc = getMethod(delegate, @selector(webView:resource:canAuthenticateAgainstProtectionSpace:forDataSource:));
   1591 #endif
   1592     cache->didReceiveContentLengthFunc = getMethod(delegate, @selector(webView:resource:didReceiveContentLength:fromDataSource:));
   1593     cache->didReceiveResponseFunc = getMethod(delegate, @selector(webView:resource:didReceiveResponse:fromDataSource:));
   1594     cache->identifierForRequestFunc = getMethod(delegate, @selector(webView:identifierForInitialRequest:fromDataSource:));
   1595     cache->plugInFailedWithErrorFunc = getMethod(delegate, @selector(webView:plugInFailedWithError:dataSource:));
   1596     cache->willCacheResponseFunc = getMethod(delegate, @selector(webView:resource:willCacheResponse:fromDataSource:));
   1597     cache->willSendRequestFunc = getMethod(delegate, @selector(webView:resource:willSendRequest:redirectResponse:fromDataSource:));
   1598     cache->shouldUseCredentialStorageFunc = getMethod(delegate, @selector(webView:resource:shouldUseCredentialStorageForDataSource:));
   1599     cache->shouldPaintBrokenImageForURLFunc = getMethod(delegate, @selector(webView:shouldPaintBrokenImageForURL:));
   1600 }
   1601 
   1602 - (void)_cacheFrameLoadDelegateImplementations
   1603 {
   1604     WebFrameLoadDelegateImplementationCache *cache = &_private->frameLoadDelegateImplementations;
   1605     id delegate = _private->frameLoadDelegate;
   1606 
   1607     if (!delegate) {
   1608         bzero(cache, sizeof(WebFrameLoadDelegateImplementationCache));
   1609         return;
   1610     }
   1611 
   1612     cache->didCancelClientRedirectForFrameFunc = getMethod(delegate, @selector(webView:didCancelClientRedirectForFrame:));
   1613     cache->didChangeLocationWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didChangeLocationWithinPageForFrame:));
   1614     cache->didPushStateWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didPushStateWithinPageForFrame:));
   1615     cache->didReplaceStateWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didReplaceStateWithinPageForFrame:));
   1616     cache->didPopStateWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didPopStateWithinPageForFrame:));
   1617     cache->didClearWindowObjectForFrameFunc = getMethod(delegate, @selector(webView:didClearWindowObject:forFrame:));
   1618     cache->didClearWindowObjectForFrameInScriptWorldFunc = getMethod(delegate, @selector(webView:didClearWindowObjectForFrame:inScriptWorld:));
   1619     cache->didClearInspectorWindowObjectForFrameFunc = getMethod(delegate, @selector(webView:didClearInspectorWindowObject:forFrame:));
   1620     cache->didCommitLoadForFrameFunc = getMethod(delegate, @selector(webView:didCommitLoadForFrame:));
   1621     cache->didFailLoadWithErrorForFrameFunc = getMethod(delegate, @selector(webView:didFailLoadWithError:forFrame:));
   1622     cache->didFailProvisionalLoadWithErrorForFrameFunc = getMethod(delegate, @selector(webView:didFailProvisionalLoadWithError:forFrame:));
   1623     cache->didFinishDocumentLoadForFrameFunc = getMethod(delegate, @selector(webView:didFinishDocumentLoadForFrame:));
   1624     cache->didFinishLoadForFrameFunc = getMethod(delegate, @selector(webView:didFinishLoadForFrame:));
   1625     cache->didFirstLayoutInFrameFunc = getMethod(delegate, @selector(webView:didFirstLayoutInFrame:));
   1626     cache->didFirstVisuallyNonEmptyLayoutInFrameFunc = getMethod(delegate, @selector(webView:didFirstVisuallyNonEmptyLayoutInFrame:));
   1627     cache->didHandleOnloadEventsForFrameFunc = getMethod(delegate, @selector(webView:didHandleOnloadEventsForFrame:));
   1628     cache->didReceiveIconForFrameFunc = getMethod(delegate, @selector(webView:didReceiveIcon:forFrame:));
   1629     cache->didReceiveServerRedirectForProvisionalLoadForFrameFunc = getMethod(delegate, @selector(webView:didReceiveServerRedirectForProvisionalLoadForFrame:));
   1630     cache->didReceiveTitleForFrameFunc = getMethod(delegate, @selector(webView:didReceiveTitle:forFrame:));
   1631     cache->didStartProvisionalLoadForFrameFunc = getMethod(delegate, @selector(webView:didStartProvisionalLoadForFrame:));
   1632     cache->willCloseFrameFunc = getMethod(delegate, @selector(webView:willCloseFrame:));
   1633     cache->willPerformClientRedirectToURLDelayFireDateForFrameFunc = getMethod(delegate, @selector(webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:));
   1634     cache->windowScriptObjectAvailableFunc = getMethod(delegate, @selector(webView:windowScriptObjectAvailable:));
   1635     cache->didDisplayInsecureContentFunc = getMethod(delegate, @selector(webViewDidDisplayInsecureContent:));
   1636     cache->didRunInsecureContentFunc = getMethod(delegate, @selector(webView:didRunInsecureContent:));
   1637 }
   1638 
   1639 - (void)_cacheScriptDebugDelegateImplementations
   1640 {
   1641     WebScriptDebugDelegateImplementationCache *cache = &_private->scriptDebugDelegateImplementations;
   1642     id delegate = _private->scriptDebugDelegate;
   1643 
   1644     if (!delegate) {
   1645         bzero(cache, sizeof(WebScriptDebugDelegateImplementationCache));
   1646         return;
   1647     }
   1648 
   1649     cache->didParseSourceFunc = getMethod(delegate, @selector(webView:didParseSource:baseLineNumber:fromURL:sourceId:forWebFrame:));
   1650     if (cache->didParseSourceFunc)
   1651         cache->didParseSourceExpectsBaseLineNumber = YES;
   1652     else {
   1653         cache->didParseSourceExpectsBaseLineNumber = NO;
   1654         cache->didParseSourceFunc = getMethod(delegate, @selector(webView:didParseSource:fromURL:sourceId:forWebFrame:));
   1655     }
   1656 
   1657     cache->failedToParseSourceFunc = getMethod(delegate, @selector(webView:failedToParseSource:baseLineNumber:fromURL:withError:forWebFrame:));
   1658     cache->didEnterCallFrameFunc = getMethod(delegate, @selector(webView:didEnterCallFrame:sourceId:line:forWebFrame:));
   1659     cache->willExecuteStatementFunc = getMethod(delegate, @selector(webView:willExecuteStatement:sourceId:line:forWebFrame:));
   1660     cache->willLeaveCallFrameFunc = getMethod(delegate, @selector(webView:willLeaveCallFrame:sourceId:line:forWebFrame:));
   1661 
   1662     cache->exceptionWasRaisedFunc = getMethod(delegate, @selector(webView:exceptionWasRaised:hasHandler:sourceId:line:forWebFrame:));
   1663     if (cache->exceptionWasRaisedFunc)
   1664         cache->exceptionWasRaisedExpectsHasHandlerFlag = YES;
   1665     else {
   1666         cache->exceptionWasRaisedExpectsHasHandlerFlag = NO;
   1667         cache->exceptionWasRaisedFunc = getMethod(delegate, @selector(webView:exceptionWasRaised:sourceId:line:forWebFrame:));
   1668     }
   1669 }
   1670 
   1671 - (void)_cacheHistoryDelegateImplementations
   1672 {
   1673     WebHistoryDelegateImplementationCache *cache = &_private->historyDelegateImplementations;
   1674     id delegate = _private->historyDelegate;
   1675 
   1676     if (!delegate) {
   1677         bzero(cache, sizeof(WebHistoryDelegateImplementationCache));
   1678         return;
   1679     }
   1680 
   1681     cache->navigatedFunc = getMethod(delegate, @selector(webView:didNavigateWithNavigationData:inFrame:));
   1682     cache->clientRedirectFunc = getMethod(delegate, @selector(webView:didPerformClientRedirectFromURL:toURL:inFrame:));
   1683     cache->serverRedirectFunc = getMethod(delegate, @selector(webView:didPerformServerRedirectFromURL:toURL:inFrame:));
   1684     cache->setTitleFunc = getMethod(delegate, @selector(webView:updateHistoryTitle:forURL:));
   1685     cache->populateVisitedLinksFunc = getMethod(delegate, @selector(populateVisitedLinksForWebView:));
   1686 }
   1687 
   1688 - (id)_policyDelegateForwarder
   1689 {
   1690     if (!_private->policyDelegateForwarder)
   1691         _private->policyDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->policyDelegate defaultTarget:[WebDefaultPolicyDelegate sharedPolicyDelegate] catchExceptions:_private->catchesDelegateExceptions];
   1692     return _private->policyDelegateForwarder;
   1693 }
   1694 
   1695 - (id)_UIDelegateForwarder
   1696 {
   1697     if (!_private->UIDelegateForwarder)
   1698         _private->UIDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->UIDelegate defaultTarget:[WebDefaultUIDelegate sharedUIDelegate] catchExceptions:_private->catchesDelegateExceptions];
   1699     return _private->UIDelegateForwarder;
   1700 }
   1701 
   1702 - (id)_editingDelegateForwarder
   1703 {
   1704     // This can be called during window deallocation by QTMovieView in the QuickTime Cocoa Plug-in.
   1705     // Not sure if that is a bug or not.
   1706     if (!_private)
   1707         return nil;
   1708 
   1709     if (!_private->editingDelegateForwarder)
   1710         _private->editingDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->editingDelegate defaultTarget:[WebDefaultEditingDelegate sharedEditingDelegate] catchExceptions:_private->catchesDelegateExceptions];
   1711     return _private->editingDelegateForwarder;
   1712 }
   1713 
   1714 - (void)_closeWindow
   1715 {
   1716     [[self _UIDelegateForwarder] webViewClose:self];
   1717 }
   1718 
   1719 + (void)_unregisterViewClassAndRepresentationClassForMIMEType:(NSString *)MIMEType
   1720 {
   1721     [[WebFrameView _viewTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType];
   1722     [[WebDataSource _repTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType];
   1723 
   1724     // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
   1725     // in the WebCore MIMEType registry.  For now we're doing this in a safe, limited manner
   1726     // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
   1727     MIMETypeRegistry::getSupportedNonImageMIMETypes().remove(MIMEType);
   1728 }
   1729 
   1730 + (void)_registerViewClass:(Class)viewClass representationClass:(Class)representationClass forURLScheme:(NSString *)URLScheme
   1731 {
   1732     NSString *MIMEType = [self _generatedMIMETypeForURLScheme:URLScheme];
   1733     [self registerViewClass:viewClass representationClass:representationClass forMIMEType:MIMEType];
   1734 
   1735     // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
   1736     // in the WebCore MIMEType registry.  For now we're doing this in a safe, limited manner
   1737     // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
   1738     if ([viewClass class] == [WebHTMLView class])
   1739         MIMETypeRegistry::getSupportedNonImageMIMETypes().add(MIMEType);
   1740 
   1741     // This is used to make _representationExistsForURLScheme faster.
   1742     // Without this set, we'd have to create the MIME type each time.
   1743     if (schemesWithRepresentationsSet == nil) {
   1744         schemesWithRepresentationsSet = [[NSMutableSet alloc] init];
   1745     }
   1746     [schemesWithRepresentationsSet addObject:[[[URLScheme lowercaseString] copy] autorelease]];
   1747 }
   1748 
   1749 + (NSString *)_generatedMIMETypeForURLScheme:(NSString *)URLScheme
   1750 {
   1751     return [@"x-apple-web-kit/" stringByAppendingString:[URLScheme lowercaseString]];
   1752 }
   1753 
   1754 + (BOOL)_representationExistsForURLScheme:(NSString *)URLScheme
   1755 {
   1756     return [schemesWithRepresentationsSet containsObject:[URLScheme lowercaseString]];
   1757 }
   1758 
   1759 + (BOOL)_canHandleRequest:(NSURLRequest *)request forMainFrame:(BOOL)forMainFrame
   1760 {
   1761     // FIXME: If <rdar://problem/5217309> gets fixed, this check can be removed.
   1762     if (!request)
   1763         return NO;
   1764 
   1765     if ([NSURLConnection canHandleRequest:request])
   1766         return YES;
   1767 
   1768     NSString *scheme = [[request URL] scheme];
   1769 
   1770     // Representations for URL schemes work at the top level.
   1771     if (forMainFrame && [self _representationExistsForURLScheme:scheme])
   1772         return YES;
   1773 
   1774     return [scheme _webkit_isCaseInsensitiveEqualToString:@"applewebdata"];
   1775 }
   1776 
   1777 + (BOOL)_canHandleRequest:(NSURLRequest *)request
   1778 {
   1779     return [self _canHandleRequest:request forMainFrame:YES];
   1780 }
   1781 
   1782 + (NSString *)_decodeData:(NSData *)data
   1783 {
   1784     HTMLNames::init(); // this method is used for importing bookmarks at startup, so HTMLNames are likely to be uninitialized yet
   1785     RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("text/html"); // bookmark files are HTML
   1786     String result = decoder->decode(static_cast<const char*>([data bytes]), [data length]);
   1787     result += decoder->flush();
   1788     return result;
   1789 }
   1790 
   1791 - (void)_pushPerformingProgrammaticFocus
   1792 {
   1793     _private->programmaticFocusCount++;
   1794 }
   1795 
   1796 - (void)_popPerformingProgrammaticFocus
   1797 {
   1798     _private->programmaticFocusCount--;
   1799 }
   1800 
   1801 - (BOOL)_isPerformingProgrammaticFocus
   1802 {
   1803     return _private->programmaticFocusCount != 0;
   1804 }
   1805 
   1806 - (void)_didChangeValueForKey: (NSString *)key
   1807 {
   1808     LOG (Bindings, "calling didChangeValueForKey: %@", key);
   1809     [self didChangeValueForKey: key];
   1810 }
   1811 
   1812 - (void)_willChangeValueForKey: (NSString *)key
   1813 {
   1814     LOG (Bindings, "calling willChangeValueForKey: %@", key);
   1815     [self willChangeValueForKey: key];
   1816 }
   1817 
   1818 + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key {
   1819     static NSSet *manualNotifyKeys = nil;
   1820     if (!manualNotifyKeys)
   1821         manualNotifyKeys = [[NSSet alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey,
   1822             _WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, _WebMainFrameDocumentKey,
   1823             nil];
   1824     if ([manualNotifyKeys containsObject:key])
   1825         return NO;
   1826     return YES;
   1827 }
   1828 
   1829 - (NSArray *)_declaredKeys {
   1830     static NSArray *declaredKeys = nil;
   1831     if (!declaredKeys)
   1832         declaredKeys = [[NSArray alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey,
   1833             _WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, _WebMainFrameDocumentKey, nil];
   1834     return declaredKeys;
   1835 }
   1836 
   1837 - (void)setObservationInfo:(void *)info
   1838 {
   1839     _private->observationInfo = info;
   1840 }
   1841 
   1842 - (void *)observationInfo
   1843 {
   1844     return _private->observationInfo;
   1845 }
   1846 
   1847 - (void)_willChangeBackForwardKeys
   1848 {
   1849     [self _willChangeValueForKey: _WebCanGoBackKey];
   1850     [self _willChangeValueForKey: _WebCanGoForwardKey];
   1851 }
   1852 
   1853 - (void)_didChangeBackForwardKeys
   1854 {
   1855     [self _didChangeValueForKey: _WebCanGoBackKey];
   1856     [self _didChangeValueForKey: _WebCanGoForwardKey];
   1857 }
   1858 
   1859 - (void)_didStartProvisionalLoadForFrame:(WebFrame *)frame
   1860 {
   1861     [self _willChangeBackForwardKeys];
   1862     if (frame == [self mainFrame]){
   1863         // Force an observer update by sending a will/did.
   1864         [self _willChangeValueForKey: _WebIsLoadingKey];
   1865         [self _didChangeValueForKey: _WebIsLoadingKey];
   1866 
   1867         [self _willChangeValueForKey: _WebMainFrameURLKey];
   1868     }
   1869 
   1870     [NSApp setWindowsNeedUpdate:YES];
   1871 }
   1872 
   1873 - (void)_didCommitLoadForFrame:(WebFrame *)frame
   1874 {
   1875     if (frame == [self mainFrame])
   1876         [self _didChangeValueForKey: _WebMainFrameURLKey];
   1877     [NSApp setWindowsNeedUpdate:YES];
   1878 }
   1879 
   1880 - (void)_didFinishLoadForFrame:(WebFrame *)frame
   1881 {
   1882     [self _didChangeBackForwardKeys];
   1883     if (frame == [self mainFrame]){
   1884         // Force an observer update by sending a will/did.
   1885         [self _willChangeValueForKey: _WebIsLoadingKey];
   1886         [self _didChangeValueForKey: _WebIsLoadingKey];
   1887     }
   1888     [NSApp setWindowsNeedUpdate:YES];
   1889 }
   1890 
   1891 - (void)_didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
   1892 {
   1893     [self _didChangeBackForwardKeys];
   1894     if (frame == [self mainFrame]){
   1895         // Force an observer update by sending a will/did.
   1896         [self _willChangeValueForKey: _WebIsLoadingKey];
   1897         [self _didChangeValueForKey: _WebIsLoadingKey];
   1898     }
   1899     [NSApp setWindowsNeedUpdate:YES];
   1900 }
   1901 
   1902 - (void)_didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
   1903 {
   1904     [self _didChangeBackForwardKeys];
   1905     if (frame == [self mainFrame]){
   1906         // Force an observer update by sending a will/did.
   1907         [self _willChangeValueForKey: _WebIsLoadingKey];
   1908         [self _didChangeValueForKey: _WebIsLoadingKey];
   1909 
   1910         [self _didChangeValueForKey: _WebMainFrameURLKey];
   1911     }
   1912     [NSApp setWindowsNeedUpdate:YES];
   1913 }
   1914 
   1915 - (NSCachedURLResponse *)_cachedResponseForURL:(NSURL *)URL
   1916 {
   1917     NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:URL];
   1918     [request _web_setHTTPUserAgent:[self userAgentForURL:URL]];
   1919     NSCachedURLResponse *cachedResponse;
   1920 #if USE(CFURLSTORAGESESSIONS)
   1921     if (CFURLStorageSessionRef storageSession = ResourceHandle::privateBrowsingStorageSession())
   1922         cachedResponse = WKCachedResponseForRequest(storageSession, request);
   1923     else
   1924 #endif
   1925         cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:request];
   1926     [request release];
   1927     return cachedResponse;
   1928 }
   1929 
   1930 - (void)_writeImageForElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
   1931 {
   1932     NSURL *linkURL = [element objectForKey:WebElementLinkURLKey];
   1933     DOMElement *domElement = [element objectForKey:WebElementDOMNodeKey];
   1934     [pasteboard _web_writeImage:(NSImage *)(domElement ? nil : [element objectForKey:WebElementImageKey])
   1935                         element:domElement
   1936                             URL:linkURL ? linkURL : (NSURL *)[element objectForKey:WebElementImageURLKey]
   1937                           title:[element objectForKey:WebElementImageAltStringKey]
   1938                         archive:[[element objectForKey:WebElementDOMNodeKey] webArchive]
   1939                           types:types
   1940                          source:nil];
   1941 }
   1942 
   1943 - (void)_writeLinkElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
   1944 {
   1945     [pasteboard _web_writeURL:[element objectForKey:WebElementLinkURLKey]
   1946                      andTitle:[element objectForKey:WebElementLinkLabelKey]
   1947                         types:types];
   1948 }
   1949 
   1950 - (void)_setInitiatedDrag:(BOOL)initiatedDrag
   1951 {
   1952     if (!_private->page)
   1953         return;
   1954     _private->page->dragController()->setDidInitiateDrag(initiatedDrag);
   1955 }
   1956 
   1957 #if ENABLE(DASHBOARD_SUPPORT)
   1958 
   1959 #define DASHBOARD_CONTROL_LABEL @"control"
   1960 
   1961 - (void)_addControlRect:(NSRect)bounds clip:(NSRect)clip fromView:(NSView *)view toDashboardRegions:(NSMutableDictionary *)regions
   1962 {
   1963     NSRect adjustedBounds = bounds;
   1964     adjustedBounds.origin = [self convertPoint:bounds.origin fromView:view];
   1965     adjustedBounds.origin.y = [self bounds].size.height - adjustedBounds.origin.y;
   1966     adjustedBounds.size = bounds.size;
   1967 
   1968     NSRect adjustedClip;
   1969     adjustedClip.origin = [self convertPoint:clip.origin fromView:view];
   1970     adjustedClip.origin.y = [self bounds].size.height - adjustedClip.origin.y;
   1971     adjustedClip.size = clip.size;
   1972 
   1973     WebDashboardRegion *region = [[WebDashboardRegion alloc] initWithRect:adjustedBounds
   1974         clip:adjustedClip type:WebDashboardRegionTypeScrollerRectangle];
   1975     NSMutableArray *scrollerRegions = [regions objectForKey:DASHBOARD_CONTROL_LABEL];
   1976     if (!scrollerRegions) {
   1977         scrollerRegions = [[NSMutableArray alloc] init];
   1978         [regions setObject:scrollerRegions forKey:DASHBOARD_CONTROL_LABEL];
   1979         [scrollerRegions release];
   1980     }
   1981     [scrollerRegions addObject:region];
   1982     [region release];
   1983 }
   1984 
   1985 - (void)_addScrollerDashboardRegionsForFrameView:(FrameView*)frameView dashboardRegions:(NSMutableDictionary *)regions
   1986 {
   1987     NSView *documentView = [[kit(frameView->frame()) frameView] documentView];
   1988 
   1989     const HashSet<RefPtr<Widget> >* children = frameView->children();
   1990     HashSet<RefPtr<Widget> >::const_iterator end = children->end();
   1991     for (HashSet<RefPtr<Widget> >::const_iterator it = children->begin(); it != end; ++it) {
   1992         Widget* widget = (*it).get();
   1993         if (widget->isFrameView()) {
   1994             [self _addScrollerDashboardRegionsForFrameView:static_cast<FrameView*>(widget) dashboardRegions:regions];
   1995             continue;
   1996         }
   1997 
   1998         if (!widget->isScrollbar())
   1999             continue;
   2000 
   2001         // FIXME: This should really pass an appropriate clip, but our first try got it wrong, and
   2002         // it's not common to need this to be correct in Dashboard widgets.
   2003         NSRect bounds = widget->frameRect();
   2004         [self _addControlRect:bounds clip:bounds fromView:documentView toDashboardRegions:regions];
   2005     }
   2006 }
   2007 
   2008 - (void)_addScrollerDashboardRegions:(NSMutableDictionary *)regions from:(NSArray *)views
   2009 {
   2010     // Add scroller regions for NSScroller and WebCore scrollbars
   2011     NSUInteger count = [views count];
   2012     for (NSUInteger i = 0; i < count; i++) {
   2013         NSView *view = [views objectAtIndex:i];
   2014 
   2015         if ([view isKindOfClass:[WebHTMLView class]]) {
   2016             if (Frame* coreFrame = core([(WebHTMLView*)view _frame])) {
   2017                 if (FrameView* coreView = coreFrame->view())
   2018                     [self _addScrollerDashboardRegionsForFrameView:coreView dashboardRegions:regions];
   2019             }
   2020         } else if ([view isKindOfClass:[NSScroller class]]) {
   2021             // AppKit places absent scrollers at -100,-100
   2022             if ([view frame].origin.y < 0)
   2023                 continue;
   2024             [self _addControlRect:[view bounds] clip:[view visibleRect] fromView:view toDashboardRegions:regions];
   2025         }
   2026         [self _addScrollerDashboardRegions:regions from:[view subviews]];
   2027     }
   2028 }
   2029 
   2030 - (void)_addScrollerDashboardRegions:(NSMutableDictionary *)regions
   2031 {
   2032     [self _addScrollerDashboardRegions:regions from:[self subviews]];
   2033 }
   2034 
   2035 - (NSDictionary *)_dashboardRegions
   2036 {
   2037     // Only return regions from main frame.
   2038     Frame* mainFrame = [self _mainCoreFrame];
   2039     if (!mainFrame)
   2040         return nil;
   2041 
   2042     const Vector<DashboardRegionValue>& regions = mainFrame->document()->dashboardRegions();
   2043     size_t size = regions.size();
   2044 
   2045     NSMutableDictionary *webRegions = [NSMutableDictionary dictionaryWithCapacity:size];
   2046     for (size_t i = 0; i < size; i++) {
   2047         const DashboardRegionValue& region = regions[i];
   2048 
   2049         if (region.type == StyleDashboardRegion::None)
   2050             continue;
   2051 
   2052         NSString *label = region.label;
   2053         WebDashboardRegionType type = WebDashboardRegionTypeNone;
   2054         if (region.type == StyleDashboardRegion::Circle)
   2055             type = WebDashboardRegionTypeCircle;
   2056         else if (region.type == StyleDashboardRegion::Rectangle)
   2057             type = WebDashboardRegionTypeRectangle;
   2058         NSMutableArray *regionValues = [webRegions objectForKey:label];
   2059         if (!regionValues) {
   2060             regionValues = [[NSMutableArray alloc] initWithCapacity:1];
   2061             [webRegions setObject:regionValues forKey:label];
   2062             [regionValues release];
   2063         }
   2064 
   2065         WebDashboardRegion *webRegion = [[WebDashboardRegion alloc] initWithRect:region.bounds clip:region.clip type:type];
   2066         [regionValues addObject:webRegion];
   2067         [webRegion release];
   2068     }
   2069 
   2070     [self _addScrollerDashboardRegions:webRegions];
   2071 
   2072     return webRegions;
   2073 }
   2074 
   2075 - (void)_setDashboardBehavior:(WebDashboardBehavior)behavior to:(BOOL)flag
   2076 {
   2077     // FIXME: Remove this blanket assignment once Dashboard and Dashcode implement
   2078     // specific support for the backward compatibility mode flag.
   2079     if (behavior == WebDashboardBehaviorAllowWheelScrolling && flag == NO && _private->page)
   2080         _private->page->settings()->setUsesDashboardBackwardCompatibilityMode(true);
   2081 
   2082     switch (behavior) {
   2083         case WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows: {
   2084             _private->dashboardBehaviorAlwaysSendMouseEventsToAllWindows = flag;
   2085             break;
   2086         }
   2087         case WebDashboardBehaviorAlwaysSendActiveNullEventsToPlugIns: {
   2088             _private->dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns = flag;
   2089             break;
   2090         }
   2091         case WebDashboardBehaviorAlwaysAcceptsFirstMouse: {
   2092             _private->dashboardBehaviorAlwaysAcceptsFirstMouse = flag;
   2093             break;
   2094         }
   2095         case WebDashboardBehaviorAllowWheelScrolling: {
   2096             _private->dashboardBehaviorAllowWheelScrolling = flag;
   2097             break;
   2098         }
   2099         case WebDashboardBehaviorUseBackwardCompatibilityMode: {
   2100             if (_private->page)
   2101                 _private->page->settings()->setUsesDashboardBackwardCompatibilityMode(flag);
   2102             break;
   2103         }
   2104     }
   2105 
   2106     // Pre-HTML5 parser quirks should be enabled if Dashboard is in backward
   2107     // compatibility mode. See <rdar://problem/8175982>.
   2108     if (_private->page)
   2109         _private->page->settings()->setUsePreHTML5ParserQuirks([self _needsPreHTML5ParserQuirks]);
   2110 }
   2111 
   2112 - (BOOL)_dashboardBehavior:(WebDashboardBehavior)behavior
   2113 {
   2114     switch (behavior) {
   2115         case WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows: {
   2116             return _private->dashboardBehaviorAlwaysSendMouseEventsToAllWindows;
   2117         }
   2118         case WebDashboardBehaviorAlwaysSendActiveNullEventsToPlugIns: {
   2119             return _private->dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns;
   2120         }
   2121         case WebDashboardBehaviorAlwaysAcceptsFirstMouse: {
   2122             return _private->dashboardBehaviorAlwaysAcceptsFirstMouse;
   2123         }
   2124         case WebDashboardBehaviorAllowWheelScrolling: {
   2125             return _private->dashboardBehaviorAllowWheelScrolling;
   2126         }
   2127         case WebDashboardBehaviorUseBackwardCompatibilityMode: {
   2128             return _private->page && _private->page->settings()->usesDashboardBackwardCompatibilityMode();
   2129         }
   2130     }
   2131     return NO;
   2132 }
   2133 
   2134 #endif /* ENABLE(DASHBOARD_SUPPORT) */
   2135 
   2136 + (void)_setShouldUseFontSmoothing:(BOOL)f
   2137 {
   2138     Font::setShouldUseSmoothing(f);
   2139 }
   2140 
   2141 + (BOOL)_shouldUseFontSmoothing
   2142 {
   2143     return Font::shouldUseSmoothing();
   2144 }
   2145 
   2146 + (void)_setUsesTestModeFocusRingColor:(BOOL)f
   2147 {
   2148     setUsesTestModeFocusRingColor(f);
   2149 }
   2150 
   2151 + (BOOL)_usesTestModeFocusRingColor
   2152 {
   2153     return usesTestModeFocusRingColor();
   2154 }
   2155 
   2156 - (void)setAlwaysShowVerticalScroller:(BOOL)flag
   2157 {
   2158     WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
   2159     if (flag) {
   2160         [scrollview setVerticalScrollingMode:ScrollbarAlwaysOn andLock:YES];
   2161     } else {
   2162         [scrollview setVerticalScrollingModeLocked:NO];
   2163         [scrollview setVerticalScrollingMode:ScrollbarAuto andLock:NO];
   2164     }
   2165 }
   2166 
   2167 - (BOOL)alwaysShowVerticalScroller
   2168 {
   2169     WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
   2170     return [scrollview verticalScrollingModeLocked] && [scrollview verticalScrollingMode] == ScrollbarAlwaysOn;
   2171 }
   2172 
   2173 - (void)setAlwaysShowHorizontalScroller:(BOOL)flag
   2174 {
   2175     WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
   2176     if (flag) {
   2177         [scrollview setHorizontalScrollingMode:ScrollbarAlwaysOn andLock:YES];
   2178     } else {
   2179         [scrollview setHorizontalScrollingModeLocked:NO];
   2180         [scrollview setHorizontalScrollingMode:ScrollbarAuto andLock:NO];
   2181     }
   2182 }
   2183 
   2184 - (void)setProhibitsMainFrameScrolling:(BOOL)prohibits
   2185 {
   2186     if (Frame* mainFrame = [self _mainCoreFrame])
   2187         mainFrame->view()->setProhibitsScrolling(prohibits);
   2188 }
   2189 
   2190 - (BOOL)alwaysShowHorizontalScroller
   2191 {
   2192     WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
   2193     return [scrollview horizontalScrollingModeLocked] && [scrollview horizontalScrollingMode] == ScrollbarAlwaysOn;
   2194 }
   2195 
   2196 - (void)_setInViewSourceMode:(BOOL)flag
   2197 {
   2198     if (Frame* mainFrame = [self _mainCoreFrame])
   2199         mainFrame->setInViewSourceMode(flag);
   2200 }
   2201 
   2202 - (BOOL)_inViewSourceMode
   2203 {
   2204     Frame* mainFrame = [self _mainCoreFrame];
   2205     return mainFrame && mainFrame->inViewSourceMode();
   2206 }
   2207 
   2208 - (void)_setUseFastImageScalingMode:(BOOL)flag
   2209 {
   2210     if (_private->page && _private->page->inLowQualityImageInterpolationMode() != flag) {
   2211         _private->page->setInLowQualityImageInterpolationMode(flag);
   2212         [self setNeedsDisplay:YES];
   2213     }
   2214 }
   2215 
   2216 - (BOOL)_inFastImageScalingMode
   2217 {
   2218     if (_private->page)
   2219         return _private->page->inLowQualityImageInterpolationMode();
   2220     return NO;
   2221 }
   2222 
   2223 - (BOOL)_cookieEnabled
   2224 {
   2225     if (_private->page)
   2226         return _private->page->cookieEnabled();
   2227     return YES;
   2228 }
   2229 
   2230 - (void)_setCookieEnabled:(BOOL)enable
   2231 {
   2232     if (_private->page)
   2233         _private->page->setCookieEnabled(enable);
   2234 }
   2235 
   2236 - (void)_setAdditionalWebPlugInPaths:(NSArray *)newPaths
   2237 {
   2238     if (!_private->pluginDatabase)
   2239         _private->pluginDatabase = [[WebPluginDatabase alloc] init];
   2240 
   2241     [_private->pluginDatabase setPlugInPaths:newPaths];
   2242     [_private->pluginDatabase refresh];
   2243 }
   2244 
   2245 - (void)_attachScriptDebuggerToAllFrames
   2246 {
   2247     for (Frame* frame = [self _mainCoreFrame]; frame; frame = frame->tree()->traverseNext())
   2248         [kit(frame) _attachScriptDebugger];
   2249 }
   2250 
   2251 - (void)_detachScriptDebuggerFromAllFrames
   2252 {
   2253     for (Frame* frame = [self _mainCoreFrame]; frame; frame = frame->tree()->traverseNext())
   2254         [kit(frame) _detachScriptDebugger];
   2255 }
   2256 
   2257 - (void)setBackgroundColor:(NSColor *)backgroundColor
   2258 {
   2259     if ([_private->backgroundColor isEqual:backgroundColor])
   2260         return;
   2261 
   2262     id old = _private->backgroundColor;
   2263     _private->backgroundColor = [backgroundColor retain];
   2264     [old release];
   2265 
   2266     [[self mainFrame] _updateBackgroundAndUpdatesWhileOffscreen];
   2267 }
   2268 
   2269 - (NSColor *)backgroundColor
   2270 {
   2271     return _private->backgroundColor;
   2272 }
   2273 
   2274 - (BOOL)defersCallbacks
   2275 {
   2276     if (!_private->page)
   2277         return NO;
   2278     return _private->page->defersLoading();
   2279 }
   2280 
   2281 - (void)setDefersCallbacks:(BOOL)defer
   2282 {
   2283     if (!_private->page)
   2284         return;
   2285     return _private->page->setDefersLoading(defer);
   2286 }
   2287 
   2288 // For backwards compatibility with the WebBackForwardList API, we honor both
   2289 // a per-WebView and a per-preferences setting for whether to use the page cache.
   2290 
   2291 - (BOOL)usesPageCache
   2292 {
   2293     return _private->usesPageCache && [[self preferences] usesPageCache];
   2294 }
   2295 
   2296 - (void)setUsesPageCache:(BOOL)usesPageCache
   2297 {
   2298     _private->usesPageCache = usesPageCache;
   2299 
   2300     // Update our own settings and post the public notification only
   2301     [self _preferencesChanged:[self preferences]];
   2302     [[self preferences] _postPreferencesChangedAPINotification];
   2303 }
   2304 
   2305 - (WebHistoryItem *)_globalHistoryItem
   2306 {
   2307     if (!_private)
   2308         return nil;
   2309 
   2310     return kit(_private->_globalHistoryItem.get());
   2311 }
   2312 
   2313 - (void)_setGlobalHistoryItem:(HistoryItem*)historyItem
   2314 {
   2315     _private->_globalHistoryItem = historyItem;
   2316 }
   2317 
   2318 - (WebTextIterator *)textIteratorForRect:(NSRect)rect
   2319 {
   2320     IntPoint rectStart(rect.origin.x, rect.origin.y);
   2321     IntPoint rectEnd(rect.origin.x + rect.size.width, rect.origin.y + rect.size.height);
   2322 
   2323     Frame* coreFrame = [self _mainCoreFrame];
   2324     if (!coreFrame)
   2325         return nil;
   2326 
   2327     VisibleSelection selectionInsideRect(coreFrame->visiblePositionForPoint(rectStart), coreFrame->visiblePositionForPoint(rectEnd));
   2328 
   2329     return [[[WebTextIterator alloc] initWithRange:kit(selectionInsideRect.toNormalizedRange().get())] autorelease];
   2330 }
   2331 
   2332 - (void)handleAuthenticationForResource:(id)identifier challenge:(NSURLAuthenticationChallenge *)challenge fromDataSource:(WebDataSource *)dataSource
   2333 {
   2334     NSWindow *window = [self hostWindow] ? [self hostWindow] : [self window];
   2335     [[WebPanelAuthenticationHandler sharedHandler] startAuthentication:challenge window:window];
   2336 }
   2337 
   2338 - (void)_clearUndoRedoOperations
   2339 {
   2340     if (!_private->page)
   2341         return;
   2342     _private->page->clearUndoRedoOperations();
   2343 }
   2344 
   2345 - (void)_setCatchesDelegateExceptions:(BOOL)f
   2346 {
   2347     _private->catchesDelegateExceptions = f;
   2348 }
   2349 
   2350 - (BOOL)_catchesDelegateExceptions
   2351 {
   2352     return _private->catchesDelegateExceptions;
   2353 }
   2354 
   2355 - (void)_executeCoreCommandByName:(NSString *)name value:(NSString *)value
   2356 {
   2357     Frame* coreFrame = [self _mainCoreFrame];
   2358     if (!coreFrame)
   2359         return;
   2360     coreFrame->editor()->command(name).execute(value);
   2361 }
   2362 
   2363 - (void)_setCustomHTMLTokenizerTimeDelay:(double)timeDelay
   2364 {
   2365     if (!_private->page)
   2366         return;
   2367     return _private->page->setCustomHTMLTokenizerTimeDelay(timeDelay);
   2368 }
   2369 
   2370 - (void)_setCustomHTMLTokenizerChunkSize:(int)chunkSize
   2371 {
   2372     if (!_private->page)
   2373         return;
   2374     return _private->page->setCustomHTMLTokenizerChunkSize(chunkSize);
   2375 }
   2376 
   2377 - (void)_clearMainFrameName
   2378 {
   2379     _private->page->mainFrame()->tree()->clearName();
   2380 }
   2381 
   2382 - (void)setSelectTrailingWhitespaceEnabled:(BOOL)flag
   2383 {
   2384     _private->selectTrailingWhitespaceEnabled = flag;
   2385     if (flag)
   2386         [self setSmartInsertDeleteEnabled:false];
   2387 }
   2388 
   2389 - (BOOL)isSelectTrailingWhitespaceEnabled
   2390 {
   2391     return _private->selectTrailingWhitespaceEnabled;
   2392 }
   2393 
   2394 - (void)setMemoryCacheDelegateCallsEnabled:(BOOL)enabled
   2395 {
   2396     _private->page->setMemoryCacheClientCallsEnabled(enabled);
   2397 }
   2398 
   2399 - (BOOL)areMemoryCacheDelegateCallsEnabled
   2400 {
   2401     return _private->page->areMemoryCacheClientCallsEnabled();
   2402 }
   2403 
   2404 - (void)_setJavaScriptURLsAreAllowed:(BOOL)areAllowed
   2405 {
   2406     _private->page->setJavaScriptURLsAreAllowed(areAllowed);
   2407 }
   2408 
   2409 + (NSCursor *)_pointingHandCursor
   2410 {
   2411     return handCursor().platformCursor();
   2412 }
   2413 
   2414 - (BOOL)_postsAcceleratedCompositingNotifications
   2415 {
   2416 #if USE(ACCELERATED_COMPOSITING)
   2417     return _private->postsAcceleratedCompositingNotifications;
   2418 #else
   2419     return NO;
   2420 #endif
   2421 
   2422 }
   2423 - (void)_setPostsAcceleratedCompositingNotifications:(BOOL)flag
   2424 {
   2425 #if USE(ACCELERATED_COMPOSITING)
   2426     _private->postsAcceleratedCompositingNotifications = flag;
   2427 #endif
   2428 }
   2429 
   2430 - (BOOL)_isUsingAcceleratedCompositing
   2431 {
   2432 #if USE(ACCELERATED_COMPOSITING)
   2433     if (_private->usesDocumentViews) {
   2434         Frame* coreFrame = [self _mainCoreFrame];
   2435         for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
   2436             NSView *documentView = [[kit(frame) frameView] documentView];
   2437             if ([documentView isKindOfClass:[WebHTMLView class]] && [(WebHTMLView *)documentView _isUsingAcceleratedCompositing])
   2438                 return YES;
   2439         }
   2440     }
   2441 #endif
   2442     return NO;
   2443 }
   2444 
   2445 - (BOOL)interactiveFormValidationEnabled
   2446 {
   2447     return _private->interactiveFormValidationEnabled;
   2448 }
   2449 
   2450 - (void)setInteractiveFormValidationEnabled:(BOOL)enabled
   2451 {
   2452     _private->interactiveFormValidationEnabled = enabled;
   2453 }
   2454 
   2455 - (int)validationMessageTimerMagnification
   2456 {
   2457     return _private->validationMessageTimerMagnification;
   2458 }
   2459 
   2460 - (void)setValidationMessageTimerMagnification:(int)newValue
   2461 {
   2462     _private->validationMessageTimerMagnification = newValue;
   2463 }
   2464 
   2465 - (BOOL)_isSoftwareRenderable
   2466 {
   2467 #if USE(ACCELERATED_COMPOSITING)
   2468     if (_private->usesDocumentViews) {
   2469         Frame* coreFrame = [self _mainCoreFrame];
   2470         for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
   2471             if (FrameView* view = frame->view()) {
   2472                 if (!view->isSoftwareRenderable())
   2473                     return NO;
   2474             }
   2475         }
   2476     }
   2477 #endif
   2478     return YES;
   2479 }
   2480 
   2481 - (void)_setIncludesFlattenedCompositingLayersWhenDrawingToBitmap:(BOOL)flag
   2482 {
   2483     _private->includesFlattenedCompositingLayersWhenDrawingToBitmap = flag;
   2484 }
   2485 
   2486 - (BOOL)_includesFlattenedCompositingLayersWhenDrawingToBitmap
   2487 {
   2488     return _private->includesFlattenedCompositingLayersWhenDrawingToBitmap;
   2489 }
   2490 
   2491 #if ENABLE(NETSCAPE_PLUGIN_API)
   2492 static WebBaseNetscapePluginView *_pluginViewForNode(DOMNode *node)
   2493 {
   2494     if (!node)
   2495         return nil;
   2496 
   2497     Node* coreNode = core(node);
   2498     if (!coreNode)
   2499         return nil;
   2500 
   2501     RenderObject* renderer = coreNode->renderer();
   2502     if (!renderer || !renderer->isWidget())
   2503         return nil;
   2504 
   2505     Widget* widget = toRenderWidget(renderer)->widget();
   2506     if (!widget || !widget->platformWidget())
   2507         return nil;
   2508 
   2509     NSView *view = widget->platformWidget();
   2510     if (![view isKindOfClass:[WebBaseNetscapePluginView class]])
   2511         return nil;
   2512 
   2513     return (WebBaseNetscapePluginView *)view;
   2514 }
   2515 #endif // ENABLE(NETSCAPE_PLUGIN_API)
   2516 
   2517 + (BOOL)_isNodeHaltedPlugin:(DOMNode *)node
   2518 {
   2519 #if ENABLE(NETSCAPE_PLUGIN_API)
   2520     return [_pluginViewForNode(node) isHalted];
   2521 #else
   2522     return YES;
   2523 #endif
   2524 }
   2525 
   2526 + (BOOL)_hasPluginForNodeBeenHalted:(DOMNode *)node
   2527 {
   2528 #if ENABLE(NETSCAPE_PLUGIN_API)
   2529     return [_pluginViewForNode(node) hasBeenHalted];
   2530 #else
   2531     return YES;
   2532 #endif
   2533 }
   2534 + (void)_restartHaltedPluginForNode:(DOMNode *)node
   2535 {
   2536 #if ENABLE(NETSCAPE_PLUGIN_API)
   2537     if (!node)
   2538         return;
   2539 
   2540     [_pluginViewForNode(node) resumeFromHalt];
   2541 #endif
   2542 }
   2543 
   2544 - (NSPasteboard *)_insertionPasteboard
   2545 {
   2546     return _private ? _private->insertionPasteboard : nil;
   2547 }
   2548 
   2549 + (void)_addOriginAccessWhitelistEntryWithSourceOrigin:(NSString *)sourceOrigin destinationProtocol:(NSString *)destinationProtocol destinationHost:(NSString *)destinationHost allowDestinationSubdomains:(BOOL)allowDestinationSubdomains
   2550 {
   2551     SecurityOrigin::addOriginAccessWhitelistEntry(*SecurityOrigin::createFromString(sourceOrigin), destinationProtocol, destinationHost, allowDestinationSubdomains);
   2552 }
   2553 
   2554 + (void)_removeOriginAccessWhitelistEntryWithSourceOrigin:(NSString *)sourceOrigin destinationProtocol:(NSString *)destinationProtocol destinationHost:(NSString *)destinationHost allowDestinationSubdomains:(BOOL)allowDestinationSubdomains
   2555 {
   2556     SecurityOrigin::removeOriginAccessWhitelistEntry(*SecurityOrigin::createFromString(sourceOrigin), destinationProtocol, destinationHost, allowDestinationSubdomains);
   2557 }
   2558 
   2559 +(void)_resetOriginAccessWhitelists
   2560 {
   2561     SecurityOrigin::resetOriginAccessWhitelists();
   2562 }
   2563 
   2564 - (void)_updateActiveState
   2565 {
   2566     if (_private && _private->page)
   2567         _private->page->focusController()->setActive([[self window] isKeyWindow]);
   2568 }
   2569 
   2570 static PassOwnPtr<Vector<String> > toStringVector(NSArray* patterns)
   2571 {
   2572     // Convert the patterns into Vectors.
   2573     NSUInteger count = [patterns count];
   2574     if (count == 0)
   2575         return 0;
   2576     Vector<String>* patternsVector = new Vector<String>;
   2577     for (NSUInteger i = 0; i < count; ++i) {
   2578         id entry = [patterns objectAtIndex:i];
   2579         if ([entry isKindOfClass:[NSString class]])
   2580             patternsVector->append(String((NSString*)entry));
   2581     }
   2582     return patternsVector;
   2583 }
   2584 
   2585 + (void)_addUserScriptToGroup:(NSString *)groupName world:(WebScriptWorld *)world source:(NSString *)source url:(NSURL *)url
   2586                     whitelist:(NSArray *)whitelist blacklist:(NSArray *)blacklist
   2587                 injectionTime:(WebUserScriptInjectionTime)injectionTime
   2588 {
   2589     [WebView _addUserScriptToGroup:groupName world:world source:source url:url whitelist:whitelist blacklist:blacklist injectionTime:injectionTime injectedFrames:WebInjectInAllFrames];
   2590 }
   2591 
   2592 + (void)_addUserScriptToGroup:(NSString *)groupName world:(WebScriptWorld *)world source:(NSString *)source url:(NSURL *)url
   2593                     whitelist:(NSArray *)whitelist blacklist:(NSArray *)blacklist
   2594                 injectionTime:(WebUserScriptInjectionTime)injectionTime
   2595                injectedFrames:(WebUserContentInjectedFrames)injectedFrames
   2596 {
   2597     String group(groupName);
   2598     if (group.isEmpty())
   2599         return;
   2600 
   2601     PageGroup* pageGroup = PageGroup::pageGroup(group);
   2602     if (!pageGroup)
   2603         return;
   2604 
   2605     pageGroup->addUserScriptToWorld(core(world), source, url, toStringVector(whitelist), toStringVector(blacklist),
   2606                                     injectionTime == WebInjectAtDocumentStart ? InjectAtDocumentStart : InjectAtDocumentEnd,
   2607                                     injectedFrames == WebInjectInAllFrames ? InjectInAllFrames : InjectInTopFrameOnly);
   2608 }
   2609 
   2610 + (void)_addUserStyleSheetToGroup:(NSString *)groupName world:(WebScriptWorld *)world source:(NSString *)source url:(NSURL *)url
   2611                         whitelist:(NSArray *)whitelist blacklist:(NSArray *)blacklist
   2612 {
   2613     [WebView _addUserStyleSheetToGroup:groupName world:world source:source url:url whitelist:whitelist blacklist:blacklist injectedFrames:WebInjectInAllFrames];
   2614 }
   2615 
   2616 + (void)_addUserStyleSheetToGroup:(NSString *)groupName world:(WebScriptWorld *)world source:(NSString *)source url:(NSURL *)url
   2617                         whitelist:(NSArray *)whitelist blacklist:(NSArray *)blacklist
   2618                    injectedFrames:(WebUserContentInjectedFrames)injectedFrames
   2619 {
   2620     String group(groupName);
   2621     if (group.isEmpty())
   2622         return;
   2623 
   2624     PageGroup* pageGroup = PageGroup::pageGroup(group);
   2625     if (!pageGroup)
   2626         return;
   2627 
   2628     pageGroup->addUserStyleSheetToWorld(core(world), source, url, toStringVector(whitelist), toStringVector(blacklist), injectedFrames == WebInjectInAllFrames ? InjectInAllFrames : InjectInTopFrameOnly);
   2629 }
   2630 
   2631 + (void)_removeUserScriptFromGroup:(NSString *)groupName world:(WebScriptWorld *)world url:(NSURL *)url
   2632 {
   2633     String group(groupName);
   2634     if (group.isEmpty())
   2635         return;
   2636 
   2637     PageGroup* pageGroup = PageGroup::pageGroup(group);
   2638     if (!pageGroup)
   2639         return;
   2640 
   2641     pageGroup->removeUserScriptFromWorld(core(world), url);
   2642 }
   2643 
   2644 + (void)_removeUserStyleSheetFromGroup:(NSString *)groupName world:(WebScriptWorld *)world url:(NSURL *)url
   2645 {
   2646     String group(groupName);
   2647     if (group.isEmpty())
   2648         return;
   2649 
   2650     PageGroup* pageGroup = PageGroup::pageGroup(group);
   2651     if (!pageGroup)
   2652         return;
   2653 
   2654     pageGroup->removeUserStyleSheetFromWorld(core(world), url);
   2655 }
   2656 
   2657 + (void)_removeUserScriptsFromGroup:(NSString *)groupName world:(WebScriptWorld *)world
   2658 {
   2659     String group(groupName);
   2660     if (group.isEmpty())
   2661         return;
   2662 
   2663     PageGroup* pageGroup = PageGroup::pageGroup(group);
   2664     if (!pageGroup)
   2665         return;
   2666 
   2667     pageGroup->removeUserScriptsFromWorld(core(world));
   2668 }
   2669 
   2670 + (void)_removeUserStyleSheetsFromGroup:(NSString *)groupName world:(WebScriptWorld *)world
   2671 {
   2672     String group(groupName);
   2673     if (group.isEmpty())
   2674         return;
   2675 
   2676     PageGroup* pageGroup = PageGroup::pageGroup(group);
   2677     if (!pageGroup)
   2678         return;
   2679 
   2680     pageGroup->removeUserStyleSheetsFromWorld(core(world));
   2681 }
   2682 
   2683 + (void)_removeAllUserContentFromGroup:(NSString *)groupName
   2684 {
   2685     String group(groupName);
   2686     if (group.isEmpty())
   2687         return;
   2688 
   2689     PageGroup* pageGroup = PageGroup::pageGroup(group);
   2690     if (!pageGroup)
   2691         return;
   2692 
   2693     pageGroup->removeAllUserContent();
   2694 }
   2695 
   2696 - (BOOL)cssAnimationsSuspended
   2697 {
   2698     return _private->cssAnimationsSuspended;
   2699 }
   2700 
   2701 - (void)setCSSAnimationsSuspended:(BOOL)suspended
   2702 {
   2703     if (suspended == _private->cssAnimationsSuspended)
   2704         return;
   2705 
   2706     _private->cssAnimationsSuspended = suspended;
   2707 
   2708     Frame* frame = core([self mainFrame]);
   2709     if (suspended)
   2710         frame->animation()->suspendAnimations();
   2711     else
   2712         frame->animation()->resumeAnimations();
   2713 }
   2714 
   2715 + (void)_setDomainRelaxationForbidden:(BOOL)forbidden forURLScheme:(NSString *)scheme
   2716 {
   2717     SecurityOrigin::setDomainRelaxationForbiddenForURLScheme(forbidden, scheme);
   2718 }
   2719 
   2720 + (void)_registerURLSchemeAsSecure:(NSString *)scheme
   2721 {
   2722     SchemeRegistry::registerURLSchemeAsSecure(scheme);
   2723 }
   2724 
   2725 - (void)_scaleWebView:(float)scale atOrigin:(NSPoint)origin
   2726 {
   2727     Frame* coreFrame = [self _mainCoreFrame];
   2728     if (!coreFrame)
   2729         return;
   2730 
   2731     coreFrame->scalePage(scale, IntPoint(origin));
   2732 }
   2733 
   2734 - (float)_viewScaleFactor
   2735 {
   2736     Frame* coreFrame = [self _mainCoreFrame];
   2737     if (!coreFrame)
   2738         return 1;
   2739 
   2740     return coreFrame->pageScaleFactor();
   2741 }
   2742 
   2743 - (void)_setUseFixedLayout:(BOOL)fixed
   2744 {
   2745     Frame* coreFrame = [self _mainCoreFrame];
   2746     if (!coreFrame)
   2747         return;
   2748 
   2749     FrameView* view = coreFrame->view();
   2750     if (!view)
   2751         return;
   2752 
   2753     view->setUseFixedLayout(fixed);
   2754     if (!fixed)
   2755         view->setFixedLayoutSize(IntSize());
   2756 }
   2757 
   2758 - (void)_setFixedLayoutSize:(NSSize)size
   2759 {
   2760     Frame* coreFrame = [self _mainCoreFrame];
   2761     if (!coreFrame)
   2762         return;
   2763 
   2764     FrameView* view = coreFrame->view();
   2765     if (!view)
   2766         return;
   2767 
   2768     view->setFixedLayoutSize(IntSize(size));
   2769     view->forceLayout();
   2770 }
   2771 
   2772 - (BOOL)_useFixedLayout
   2773 {
   2774     Frame* coreFrame = [self _mainCoreFrame];
   2775     if (!coreFrame)
   2776         return NO;
   2777 
   2778     FrameView* view = coreFrame->view();
   2779     if (!view)
   2780         return NO;
   2781 
   2782     return view->useFixedLayout();
   2783 }
   2784 
   2785 - (NSSize)_fixedLayoutSize
   2786 {
   2787     Frame* coreFrame = [self _mainCoreFrame];
   2788     if (!coreFrame)
   2789         return IntSize();
   2790 
   2791     FrameView* view = coreFrame->view();
   2792     if (!view)
   2793         return IntSize();
   2794 
   2795     return view->fixedLayoutSize();
   2796 }
   2797 
   2798 - (NSUInteger)markAllMatchesForText:(NSString *)string caseSensitive:(BOOL)caseFlag highlight:(BOOL)highlight limit:(NSUInteger)limit
   2799 {
   2800     return [self countMatchesForText:string options:(caseFlag ? 0 : WebFindOptionsCaseInsensitive) highlight:highlight limit:limit markMatches:YES];
   2801 }
   2802 
   2803 - (NSUInteger)countMatchesForText:(NSString *)string caseSensitive:(BOOL)caseFlag highlight:(BOOL)highlight limit:(NSUInteger)limit markMatches:(BOOL)markMatches
   2804 {
   2805     return [self countMatchesForText:string options:(caseFlag ? 0 : WebFindOptionsCaseInsensitive) highlight:highlight limit:limit markMatches:markMatches];
   2806 }
   2807 
   2808 - (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag startInSelection:(BOOL)startInSelection
   2809 {
   2810     return [self findString:string options:((forward ? 0 : WebFindOptionsBackwards) | (caseFlag ? 0 : WebFindOptionsCaseInsensitive) | (wrapFlag ? WebFindOptionsWrapAround : 0) | (startInSelection ? WebFindOptionsStartInSelection : 0))];
   2811 }
   2812 
   2813 + (void)_setLoadResourcesSerially:(BOOL)serialize
   2814 {
   2815     resourceLoadScheduler()->setSerialLoadingEnabled(serialize);
   2816 }
   2817 
   2818 + (double)_defaultMinimumTimerInterval
   2819 {
   2820     return Settings::defaultMinDOMTimerInterval();
   2821 }
   2822 
   2823 - (void)_setMinimumTimerInterval:(double)intervalInSeconds
   2824 {
   2825     if (_private->page)
   2826         _private->page->settings()->setMinDOMTimerInterval(intervalInSeconds);
   2827 }
   2828 
   2829 + (BOOL)_HTTPPipeliningEnabled
   2830 {
   2831     return ResourceRequest::httpPipeliningEnabled();
   2832 }
   2833 
   2834 + (void)_setHTTPPipeliningEnabled:(BOOL)enabled
   2835 {
   2836     ResourceRequest::setHTTPPipeliningEnabled(enabled);
   2837 }
   2838 
   2839 @end
   2840 
   2841 @implementation _WebSafeForwarder
   2842 
   2843 // Used to send messages to delegates that implement informal protocols.
   2844 
   2845 - (id)initWithTarget:(id)t defaultTarget:(id)dt catchExceptions:(BOOL)c
   2846 {
   2847     self = [super init];
   2848     if (!self)
   2849         return nil;
   2850     target = t; // Non retained.
   2851     defaultTarget = dt;
   2852     catchExceptions = c;
   2853     return self;
   2854 }
   2855 
   2856 - (void)forwardInvocation:(NSInvocation *)invocation
   2857 {
   2858     if ([target respondsToSelector:[invocation selector]]) {
   2859         if (catchExceptions) {
   2860             @try {
   2861                 [invocation invokeWithTarget:target];
   2862             } @catch(id exception) {
   2863                 ReportDiscardedDelegateException([invocation selector], exception);
   2864             }
   2865         } else
   2866             [invocation invokeWithTarget:target];
   2867         return;
   2868     }
   2869 
   2870     if ([defaultTarget respondsToSelector:[invocation selector]])
   2871         [invocation invokeWithTarget:defaultTarget];
   2872 
   2873     // Do nothing quietly if method not implemented.
   2874 }
   2875 
   2876 - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
   2877 {
   2878     return [defaultTarget methodSignatureForSelector:aSelector];
   2879 }
   2880 
   2881 @end
   2882 
   2883 @implementation WebView
   2884 
   2885 + (void)initialize
   2886 {
   2887     static BOOL initialized = NO;
   2888     if (initialized)
   2889         return;
   2890     initialized = YES;
   2891 
   2892     InitWebCoreSystemInterface();
   2893     JSC::initializeThreading();
   2894     WTF::initializeMainThreadToProcessMainThread();
   2895 
   2896     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_applicationWillTerminate) name:NSApplicationWillTerminateNotification object:NSApp];
   2897     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:) name:WebPreferencesChangedInternalNotification object:nil];
   2898     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesRemovedNotification:) name:WebPreferencesRemovedNotification object:nil];
   2899 
   2900     continuousSpellCheckingEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebContinuousSpellCheckingEnabled];
   2901 #ifndef BUILDING_ON_TIGER
   2902     grammarCheckingEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebGrammarCheckingEnabled];
   2903 #endif
   2904 
   2905 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
   2906     automaticQuoteSubstitutionEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticQuoteSubstitutionEnabled];
   2907     automaticLinkDetectionEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticLinkDetectionEnabled];
   2908     automaticDashSubstitutionEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticDashSubstitutionEnabled];
   2909     automaticTextReplacementEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticTextReplacementEnabled];
   2910     automaticSpellingCorrectionEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticSpellingCorrectionEnabled];
   2911 #endif
   2912 
   2913 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
   2914     if (![[NSUserDefaults standardUserDefaults] objectForKey:WebAutomaticTextReplacementEnabled])
   2915         automaticTextReplacementEnabled = [NSSpellChecker isAutomaticTextReplacementEnabled];
   2916     if (![[NSUserDefaults standardUserDefaults] objectForKey:WebAutomaticSpellingCorrectionEnabled])
   2917         automaticSpellingCorrectionEnabled = [NSSpellChecker isAutomaticSpellingCorrectionEnabled];
   2918 #endif
   2919 }
   2920 
   2921 + (void)_applicationWillTerminate
   2922 {
   2923     applicationIsTerminating = YES;
   2924 
   2925     if (fastDocumentTeardownEnabled())
   2926         [self closeAllWebViews];
   2927 
   2928     if (!pluginDatabaseClientCount)
   2929         [WebPluginDatabase closeSharedDatabase];
   2930 
   2931     PageGroup::closeLocalStorage();
   2932 }
   2933 
   2934 + (BOOL)_canShowMIMEType:(NSString *)MIMEType allowingPlugins:(BOOL)allowPlugins
   2935 {
   2936     return [self _viewClass:nil andRepresentationClass:nil forMIMEType:MIMEType allowingPlugins:allowPlugins];
   2937 }
   2938 
   2939 + (BOOL)canShowMIMEType:(NSString *)MIMEType
   2940 {
   2941     return [self _canShowMIMEType:MIMEType allowingPlugins:YES];
   2942 }
   2943 
   2944 - (BOOL)_canShowMIMEType:(NSString *)MIMEType
   2945 {
   2946     return [[self class] _canShowMIMEType:MIMEType allowingPlugins:[_private->preferences arePlugInsEnabled]];
   2947 }
   2948 
   2949 - (WebBasePluginPackage *)_pluginForMIMEType:(NSString *)MIMEType
   2950 {
   2951     if (![_private->preferences arePlugInsEnabled])
   2952         return nil;
   2953 
   2954     WebBasePluginPackage *pluginPackage = [[WebPluginDatabase sharedDatabase] pluginForMIMEType:MIMEType];
   2955     if (pluginPackage)
   2956         return pluginPackage;
   2957 
   2958     if (_private->pluginDatabase)
   2959         return [_private->pluginDatabase pluginForMIMEType:MIMEType];
   2960 
   2961     return nil;
   2962 }
   2963 
   2964 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
   2965 - (WebBasePluginPackage *)_videoProxyPluginForMIMEType:(NSString *)MIMEType
   2966 {
   2967     WebBasePluginPackage *pluginPackage = [[WebPluginDatabase sharedDatabase] pluginForMIMEType:MIMEType];
   2968     if (pluginPackage)
   2969         return pluginPackage;
   2970 
   2971     if (_private->pluginDatabase)
   2972         return [_private->pluginDatabase pluginForMIMEType:MIMEType];
   2973 
   2974     return nil;
   2975 }
   2976 #endif
   2977 
   2978 - (WebBasePluginPackage *)_pluginForExtension:(NSString *)extension
   2979 {
   2980     if (![_private->preferences arePlugInsEnabled])
   2981         return nil;
   2982 
   2983     WebBasePluginPackage *pluginPackage = [[WebPluginDatabase sharedDatabase] pluginForExtension:extension];
   2984     if (pluginPackage)
   2985         return pluginPackage;
   2986 
   2987     if (_private->pluginDatabase)
   2988         return [_private->pluginDatabase pluginForExtension:extension];
   2989 
   2990     return nil;
   2991 }
   2992 
   2993 - (void)addPluginInstanceView:(NSView *)view
   2994 {
   2995     if (!_private->pluginDatabase)
   2996         _private->pluginDatabase = [[WebPluginDatabase alloc] init];
   2997     [_private->pluginDatabase addPluginInstanceView:view];
   2998 }
   2999 
   3000 - (void)removePluginInstanceView:(NSView *)view
   3001 {
   3002     if (_private->pluginDatabase)
   3003         [_private->pluginDatabase removePluginInstanceView:view];
   3004 }
   3005 
   3006 - (void)removePluginInstanceViewsFor:(WebFrame*)webFrame
   3007 {
   3008     if (_private->pluginDatabase)
   3009         [_private->pluginDatabase removePluginInstanceViewsFor:webFrame];
   3010 }
   3011 
   3012 - (BOOL)_isMIMETypeRegisteredAsPlugin:(NSString *)MIMEType
   3013 {
   3014     if (![_private->preferences arePlugInsEnabled])
   3015         return NO;
   3016 
   3017     if ([[WebPluginDatabase sharedDatabase] isMIMETypeRegistered:MIMEType])
   3018         return YES;
   3019 
   3020     if (_private->pluginDatabase && [_private->pluginDatabase isMIMETypeRegistered:MIMEType])
   3021         return YES;
   3022 
   3023     return NO;
   3024 }
   3025 
   3026 + (BOOL)canShowMIMETypeAsHTML:(NSString *)MIMEType
   3027 {
   3028     return [WebFrameView _canShowMIMETypeAsHTML:MIMEType];
   3029 }
   3030 
   3031 + (NSArray *)MIMETypesShownAsHTML
   3032 {
   3033     NSMutableDictionary *viewTypes = [WebFrameView _viewTypesAllowImageTypeOmission:YES];
   3034     NSEnumerator *enumerator = [viewTypes keyEnumerator];
   3035     id key;
   3036     NSMutableArray *array = [[[NSMutableArray alloc] init] autorelease];
   3037 
   3038     while ((key = [enumerator nextObject])) {
   3039         if ([viewTypes objectForKey:key] == [WebHTMLView class])
   3040             [array addObject:key];
   3041     }
   3042 
   3043     return array;
   3044 }
   3045 
   3046 + (void)setMIMETypesShownAsHTML:(NSArray *)MIMETypes
   3047 {
   3048     NSDictionary *viewTypes = [[WebFrameView _viewTypesAllowImageTypeOmission:YES] copy];
   3049     NSEnumerator *enumerator = [viewTypes keyEnumerator];
   3050     id key;
   3051     while ((key = [enumerator nextObject])) {
   3052         if ([viewTypes objectForKey:key] == [WebHTMLView class])
   3053             [WebView _unregisterViewClassAndRepresentationClassForMIMEType:key];
   3054     }
   3055 
   3056     int i, count = [MIMETypes count];
   3057     for (i = 0; i < count; i++) {
   3058         [WebView registerViewClass:[WebHTMLView class]
   3059                 representationClass:[WebHTMLRepresentation class]
   3060                 forMIMEType:[MIMETypes objectAtIndex:i]];
   3061     }
   3062     [viewTypes release];
   3063 }
   3064 
   3065 + (NSURL *)URLFromPasteboard:(NSPasteboard *)pasteboard
   3066 {
   3067     return [pasteboard _web_bestURL];
   3068 }
   3069 
   3070 + (NSString *)URLTitleFromPasteboard:(NSPasteboard *)pasteboard
   3071 {
   3072     return [pasteboard stringForType:WebURLNamePboardType];
   3073 }
   3074 
   3075 + (void)registerURLSchemeAsLocal:(NSString *)protocol
   3076 {
   3077     SchemeRegistry::registerURLSchemeAsLocal(protocol);
   3078 }
   3079 
   3080 - (id)_initWithArguments:(NSDictionary *) arguments
   3081 {
   3082     NSCoder *decoder = [arguments objectForKey:@"decoder"];
   3083     if (decoder) {
   3084         self = [self initWithCoder:decoder];
   3085     } else {
   3086         ASSERT([arguments objectForKey:@"frame"]);
   3087         NSValue *frameValue = [arguments objectForKey:@"frame"];
   3088         NSRect frame = (frameValue ? [frameValue rectValue] : NSZeroRect);
   3089         NSString *frameName = [arguments objectForKey:@"frameName"];
   3090         NSString *groupName = [arguments objectForKey:@"groupName"];
   3091         self = [self initWithFrame:frame frameName:frameName groupName:groupName];
   3092     }
   3093 
   3094     return self;
   3095 }
   3096 
   3097 static bool clientNeedsWebViewInitThreadWorkaround()
   3098 {
   3099     if (WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_WEBVIEW_INIT_THREAD_WORKAROUND))
   3100         return false;
   3101 
   3102     NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
   3103 
   3104     // Installer.
   3105     if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.installer"])
   3106         return true;
   3107 
   3108     // Automator.
   3109     if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.Automator"])
   3110         return true;
   3111 
   3112     // Automator Runner.
   3113     if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.AutomatorRunner"])
   3114         return true;
   3115 
   3116     // Automator workflows.
   3117     if ([bundleIdentifier _webkit_hasCaseInsensitivePrefix:@"com.apple.Automator."])
   3118         return true;
   3119 
   3120 #if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
   3121     // Mail.
   3122     if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.Mail"])
   3123         return true;
   3124 #endif
   3125 
   3126     return false;
   3127 }
   3128 
   3129 static bool needsWebViewInitThreadWorkaround()
   3130 {
   3131     static bool isOldClient = clientNeedsWebViewInitThreadWorkaround();
   3132     return isOldClient && !pthread_main_np();
   3133 }
   3134 
   3135 - (id)initWithFrame:(NSRect)f
   3136 {
   3137     return [self initWithFrame:f frameName:nil groupName:nil];
   3138 }
   3139 
   3140 - (id)initWithFrame:(NSRect)f frameName:(NSString *)frameName groupName:(NSString *)groupName
   3141 {
   3142     if (needsWebViewInitThreadWorkaround())
   3143         return [[self _webkit_invokeOnMainThread] initWithFrame:f frameName:frameName groupName:groupName];
   3144 
   3145     WebCoreThreadViolationCheckRoundTwo();
   3146     return [self _initWithFrame:f frameName:frameName groupName:groupName usesDocumentViews:YES];
   3147 }
   3148 
   3149 - (id)initWithCoder:(NSCoder *)decoder
   3150 {
   3151     if (needsWebViewInitThreadWorkaround())
   3152         return [[self _webkit_invokeOnMainThread] initWithCoder:decoder];
   3153 
   3154     WebCoreThreadViolationCheckRoundTwo();
   3155     WebView *result = nil;
   3156 
   3157     @try {
   3158         NSString *frameName;
   3159         NSString *groupName;
   3160         WebPreferences *preferences;
   3161         BOOL useBackForwardList = NO;
   3162         BOOL allowsUndo = YES;
   3163 
   3164         result = [super initWithCoder:decoder];
   3165         result->_private = [[WebViewPrivate alloc] init];
   3166 
   3167         // We don't want any of the archived subviews. The subviews will always
   3168         // be created in _commonInitializationFrameName:groupName:.
   3169         [[result subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
   3170 
   3171         if ([decoder allowsKeyedCoding]) {
   3172             frameName = [decoder decodeObjectForKey:@"FrameName"];
   3173             groupName = [decoder decodeObjectForKey:@"GroupName"];
   3174             preferences = [decoder decodeObjectForKey:@"Preferences"];
   3175             useBackForwardList = [decoder decodeBoolForKey:@"UseBackForwardList"];
   3176             if ([decoder containsValueForKey:@"AllowsUndo"])
   3177                 allowsUndo = [decoder decodeBoolForKey:@"AllowsUndo"];
   3178         } else {
   3179             int version;
   3180             [decoder decodeValueOfObjCType:@encode(int) at:&version];
   3181             frameName = [decoder decodeObject];
   3182             groupName = [decoder decodeObject];
   3183             preferences = [decoder decodeObject];
   3184             if (version > 1)
   3185                 [decoder decodeValuesOfObjCTypes:"c", &useBackForwardList];
   3186             // The allowsUndo field is no longer written out in encodeWithCoder, but since there are
   3187             // version 3 NIBs that have this field encoded, we still need to read it in.
   3188             if (version == 3)
   3189                 [decoder decodeValuesOfObjCTypes:"c", &allowsUndo];
   3190         }
   3191 
   3192         if (![frameName isKindOfClass:[NSString class]])
   3193             frameName = nil;
   3194         if (![groupName isKindOfClass:[NSString class]])
   3195             groupName = nil;
   3196         if (![preferences isKindOfClass:[WebPreferences class]])
   3197             preferences = nil;
   3198 
   3199         LOG(Encoding, "FrameName = %@, GroupName = %@, useBackForwardList = %d\n", frameName, groupName, (int)useBackForwardList);
   3200         [result _commonInitializationWithFrameName:frameName groupName:groupName usesDocumentViews:YES];
   3201         static_cast<BackForwardListImpl*>([result page]->backForwardList())->setEnabled(useBackForwardList);
   3202         result->_private->allowsUndo = allowsUndo;
   3203         if (preferences)
   3204             [result setPreferences:preferences];
   3205     } @catch (NSException *localException) {
   3206         result = nil;
   3207         [self release];
   3208     }
   3209 
   3210     return result;
   3211 }
   3212 
   3213 - (void)encodeWithCoder:(NSCoder *)encoder
   3214 {
   3215     // Set asside the subviews before we archive. We don't want to archive any subviews.
   3216     // The subviews will always be created in _commonInitializationFrameName:groupName:.
   3217     id originalSubviews = _subviews;
   3218     _subviews = nil;
   3219 
   3220     [super encodeWithCoder:encoder];
   3221 
   3222     // Restore the subviews we set aside.
   3223     _subviews = originalSubviews;
   3224 
   3225     BOOL useBackForwardList = _private->page && static_cast<BackForwardListImpl*>(_private->page->backForwardList())->enabled();
   3226     if ([encoder allowsKeyedCoding]) {
   3227         [encoder encodeObject:[[self mainFrame] name] forKey:@"FrameName"];
   3228         [encoder encodeObject:[self groupName] forKey:@"GroupName"];
   3229         [encoder encodeObject:[self preferences] forKey:@"Preferences"];
   3230         [encoder encodeBool:useBackForwardList forKey:@"UseBackForwardList"];
   3231         [encoder encodeBool:_private->allowsUndo forKey:@"AllowsUndo"];
   3232     } else {
   3233         int version = WebViewVersion;
   3234         [encoder encodeValueOfObjCType:@encode(int) at:&version];
   3235         [encoder encodeObject:[[self mainFrame] name]];
   3236         [encoder encodeObject:[self groupName]];
   3237         [encoder encodeObject:[self preferences]];
   3238         [encoder encodeValuesOfObjCTypes:"c", &useBackForwardList];
   3239         // DO NOT encode any new fields here, doing so will break older WebKit releases.
   3240     }
   3241 
   3242     LOG(Encoding, "FrameName = %@, GroupName = %@, useBackForwardList = %d\n", [[self mainFrame] name], [self groupName], (int)useBackForwardList);
   3243 }
   3244 
   3245 - (void)dealloc
   3246 {
   3247     if (WebCoreObjCScheduleDeallocateOnMainThread([WebView class], self))
   3248         return;
   3249 
   3250     // call close to ensure we tear-down completely
   3251     // this maintains our old behavior for existing applications
   3252     [self close];
   3253 
   3254     if ([[self class] shouldIncludeInWebKitStatistics])
   3255         --WebViewCount;
   3256 
   3257     if ([self _needsFrameLoadDelegateRetainQuirk])
   3258         [_private->frameLoadDelegate release];
   3259 
   3260     [_private release];
   3261     // [super dealloc] can end up dispatching against _private (3466082)
   3262     _private = nil;
   3263 
   3264     [super dealloc];
   3265 }
   3266 
   3267 - (void)finalize
   3268 {
   3269     ASSERT(_private->closed);
   3270 
   3271     --WebViewCount;
   3272 
   3273     [super finalize];
   3274 }
   3275 
   3276 - (void)close
   3277 {
   3278     // _close existed first, and some clients might be calling or overriding it, so call through.
   3279     [self _close];
   3280 }
   3281 
   3282 - (void)setShouldCloseWithWindow:(BOOL)close
   3283 {
   3284     _private->shouldCloseWithWindow = close;
   3285 }
   3286 
   3287 - (BOOL)shouldCloseWithWindow
   3288 {
   3289     return _private->shouldCloseWithWindow;
   3290 }
   3291 
   3292 - (void)addWindowObserversForWindow:(NSWindow *)window
   3293 {
   3294     if (window) {
   3295         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowDidBecomeKey:)
   3296             name:NSWindowDidBecomeKeyNotification object:nil];
   3297         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowDidResignKey:)
   3298             name:NSWindowDidResignKeyNotification object:nil];
   3299         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillOrderOnScreen:)
   3300             name:WKWindowWillOrderOnScreenNotification() object:window];
   3301     }
   3302 }
   3303 
   3304 - (void)removeWindowObservers
   3305 {
   3306     NSWindow *window = [self window];
   3307     if (window) {
   3308         [[NSNotificationCenter defaultCenter] removeObserver:self
   3309             name:NSWindowDidBecomeKeyNotification object:nil];
   3310         [[NSNotificationCenter defaultCenter] removeObserver:self
   3311             name:NSWindowDidResignKeyNotification object:nil];
   3312         [[NSNotificationCenter defaultCenter] removeObserver:self
   3313             name:WKWindowWillOrderOnScreenNotification() object:window];
   3314     }
   3315 }
   3316 
   3317 - (void)viewWillMoveToWindow:(NSWindow *)window
   3318 {
   3319     // Don't do anything if the WebView isn't initialized.
   3320     // This happens when decoding a WebView in a nib.
   3321     // FIXME: What sets up the observer of NSWindowWillCloseNotification in this case?
   3322     if (!_private || _private->closed)
   3323         return;
   3324 
   3325     if ([self window] && [self window] != [self hostWindow])
   3326         [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowWillCloseNotification object:[self window]];
   3327 
   3328     if (window) {
   3329         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillClose:) name:NSWindowWillCloseNotification object:window];
   3330 
   3331         // Ensure that we will receive the events that WebHTMLView (at least) needs.
   3332         // The following are expensive enough that we don't want to call them over
   3333         // and over, so do them when we move into a window.
   3334         [window setAcceptsMouseMovedEvents:YES];
   3335         WKSetNSWindowShouldPostEventNotifications(window, YES);
   3336     } else {
   3337         _private->page->setCanStartMedia(false);
   3338         _private->page->willMoveOffscreen();
   3339     }
   3340 
   3341     if (window != [self window]) {
   3342         [self removeWindowObservers];
   3343         [self addWindowObserversForWindow:window];
   3344     }
   3345 }
   3346 
   3347 - (void)viewDidMoveToWindow
   3348 {
   3349     // Don't do anything if we aren't initialized.  This happens
   3350     // when decoding a WebView.  When WebViews are decoded their subviews
   3351     // are created by initWithCoder: and so won't be normally
   3352     // initialized.  The stub views are discarded by WebView.
   3353     if (!_private || _private->closed)
   3354         return;
   3355 
   3356     if ([self window]) {
   3357         _private->page->setCanStartMedia(true);
   3358         _private->page->didMoveOnscreen();
   3359     }
   3360 
   3361     [self _updateActiveState];
   3362 }
   3363 
   3364 - (void)_windowDidBecomeKey:(NSNotification *)notification
   3365 {
   3366     NSWindow *keyWindow = [notification object];
   3367     if (keyWindow == [self window] || keyWindow == [[self window] attachedSheet])
   3368         [self _updateActiveState];
   3369 }
   3370 
   3371 - (void)_windowDidResignKey:(NSNotification *)notification
   3372 {
   3373     NSWindow *formerKeyWindow = [notification object];
   3374     if (formerKeyWindow == [self window] || formerKeyWindow == [[self window] attachedSheet])
   3375         [self _updateActiveState];
   3376 }
   3377 
   3378 - (void)_windowWillOrderOnScreen:(NSNotification *)notification
   3379 {
   3380     if (![self shouldUpdateWhileOffscreen])
   3381         [self setNeedsDisplay:YES];
   3382 }
   3383 
   3384 - (void)_windowWillClose:(NSNotification *)notification
   3385 {
   3386     if ([self shouldCloseWithWindow] && ([self window] == [self hostWindow] || ([self window] && ![self hostWindow]) || (![self window] && [self hostWindow])))
   3387         [self close];
   3388 }
   3389 
   3390 - (void)setPreferences:(WebPreferences *)prefs
   3391 {
   3392     if (!prefs)
   3393         prefs = [WebPreferences standardPreferences];
   3394 
   3395     if (_private->preferences == prefs)
   3396         return;
   3397 
   3398     [prefs willAddToWebView];
   3399 
   3400     WebPreferences *oldPrefs = _private->preferences;
   3401 
   3402     [[NSNotificationCenter defaultCenter] removeObserver:self name:WebPreferencesChangedInternalNotification object:[self preferences]];
   3403     [WebPreferences _removeReferenceForIdentifier:[oldPrefs identifier]];
   3404 
   3405     _private->preferences = [prefs retain];
   3406 
   3407     // After registering for the notification, post it so the WebCore settings update.
   3408     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:)
   3409         name:WebPreferencesChangedInternalNotification object:[self preferences]];
   3410     [self _preferencesChanged:[self preferences]];
   3411     [[self preferences] _postPreferencesChangedAPINotification];
   3412 
   3413     [oldPrefs didRemoveFromWebView];
   3414     [oldPrefs release];
   3415 }
   3416 
   3417 - (WebPreferences *)preferences
   3418 {
   3419     return _private->preferences;
   3420 }
   3421 
   3422 - (void)setPreferencesIdentifier:(NSString *)anIdentifier
   3423 {
   3424     if (!_private->closed && ![anIdentifier isEqual:[[self preferences] identifier]]) {
   3425         WebPreferences *prefs = [[WebPreferences alloc] initWithIdentifier:anIdentifier];
   3426         [self setPreferences:prefs];
   3427         [prefs release];
   3428     }
   3429 }
   3430 
   3431 - (NSString *)preferencesIdentifier
   3432 {
   3433     return [[self preferences] identifier];
   3434 }
   3435 
   3436 
   3437 - (void)setUIDelegate:delegate
   3438 {
   3439     _private->UIDelegate = delegate;
   3440     [_private->UIDelegateForwarder release];
   3441     _private->UIDelegateForwarder = nil;
   3442 }
   3443 
   3444 - (id)UIDelegate
   3445 {
   3446     return _private->UIDelegate;
   3447 }
   3448 
   3449 - (void)setResourceLoadDelegate: delegate
   3450 {
   3451     _private->resourceProgressDelegate = delegate;
   3452     [self _cacheResourceLoadDelegateImplementations];
   3453 }
   3454 
   3455 - (id)resourceLoadDelegate
   3456 {
   3457     return _private->resourceProgressDelegate;
   3458 }
   3459 
   3460 - (void)setDownloadDelegate: delegate
   3461 {
   3462     _private->downloadDelegate = delegate;
   3463 }
   3464 
   3465 
   3466 - (id)downloadDelegate
   3467 {
   3468     return _private->downloadDelegate;
   3469 }
   3470 
   3471 - (void)setPolicyDelegate:delegate
   3472 {
   3473     _private->policyDelegate = delegate;
   3474     [_private->policyDelegateForwarder release];
   3475     _private->policyDelegateForwarder = nil;
   3476 }
   3477 
   3478 - (id)policyDelegate
   3479 {
   3480     return _private->policyDelegate;
   3481 }
   3482 
   3483 - (void)setFrameLoadDelegate:delegate
   3484 {
   3485     // <rdar://problem/6950660> - Due to some subtle WebKit changes - presumably to delegate callback behavior - we've
   3486     // unconvered a latent bug in at least one WebKit app where the delegate wasn't properly retained by the app and
   3487     // was dealloc'ed before being cleared.
   3488     // This is an effort to keep such apps working for now.
   3489     if ([self _needsFrameLoadDelegateRetainQuirk]) {
   3490         [delegate retain];
   3491         [_private->frameLoadDelegate release];
   3492     }
   3493 
   3494     _private->frameLoadDelegate = delegate;
   3495     [self _cacheFrameLoadDelegateImplementations];
   3496 
   3497 #if ENABLE(ICONDATABASE)
   3498     // If this delegate wants callbacks for icons, fire up the icon database.
   3499     if (_private->frameLoadDelegateImplementations.didReceiveIconForFrameFunc)
   3500         [WebIconDatabase sharedIconDatabase];
   3501 #endif
   3502 }
   3503 
   3504 - (id)frameLoadDelegate
   3505 {
   3506     return _private->frameLoadDelegate;
   3507 }
   3508 
   3509 - (WebFrame *)mainFrame
   3510 {
   3511     // This can be called in initialization, before _private has been set up (3465613)
   3512     if (!_private || !_private->page)
   3513         return nil;
   3514     return kit(_private->page->mainFrame());
   3515 }
   3516 
   3517 - (WebFrame *)selectedFrame
   3518 {
   3519     if (_private->usesDocumentViews) {
   3520         // If the first responder is a view in our tree, we get the frame containing the first responder.
   3521         // This is faster than searching the frame hierarchy, and will give us a result even in the case
   3522         // where the focused frame doesn't actually contain a selection.
   3523         WebFrame *focusedFrame = [self _focusedFrame];
   3524         if (focusedFrame)
   3525             return focusedFrame;
   3526     }
   3527 
   3528     // If the first responder is outside of our view tree, we search for a frame containing a selection.
   3529     // There should be at most only one of these.
   3530     return [[self mainFrame] _findFrameWithSelection];
   3531 }
   3532 
   3533 - (WebBackForwardList *)backForwardList
   3534 {
   3535     if (!_private->page)
   3536         return nil;
   3537     BackForwardListImpl* list = static_cast<BackForwardListImpl*>(_private->page->backForwardList());
   3538     if (!list->enabled())
   3539         return nil;
   3540     return kit(list);
   3541 }
   3542 
   3543 - (void)setMaintainsBackForwardList:(BOOL)flag
   3544 {
   3545     if (!_private->page)
   3546         return;
   3547     static_cast<BackForwardListImpl*>(_private->page->backForwardList())->setEnabled(flag);
   3548 }
   3549 
   3550 - (BOOL)goBack
   3551 {
   3552     if (!_private->page)
   3553         return NO;
   3554 
   3555     return _private->page->goBack();
   3556 }
   3557 
   3558 - (BOOL)goForward
   3559 {
   3560     if (!_private->page)
   3561         return NO;
   3562 
   3563     return _private->page->goForward();
   3564 }
   3565 
   3566 - (BOOL)goToBackForwardItem:(WebHistoryItem *)item
   3567 {
   3568     if (!_private->page)
   3569         return NO;
   3570 
   3571     _private->page->goToItem(core(item), FrameLoadTypeIndexedBackForward);
   3572     return YES;
   3573 }
   3574 
   3575 - (void)setTextSizeMultiplier:(float)m
   3576 {
   3577     [self _setZoomMultiplier:m isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
   3578 }
   3579 
   3580 - (float)textSizeMultiplier
   3581 {
   3582     return [self _realZoomMultiplierIsTextOnly] ? _private->zoomMultiplier : 1.0f;
   3583 }
   3584 
   3585 - (void)_setZoomMultiplier:(float)multiplier isTextOnly:(BOOL)isTextOnly
   3586 {
   3587     // NOTE: This has no visible effect when viewing a PDF (see <rdar://problem/4737380>)
   3588     _private->zoomMultiplier = multiplier;
   3589     _private->zoomsTextOnly = isTextOnly;
   3590 
   3591     // FIXME: It might be nice to rework this code so that _private->zoomMultiplier doesn't exist
   3592     // and instead the zoom factors stored in Frame are used.
   3593     Frame* coreFrame = [self _mainCoreFrame];
   3594     if (coreFrame) {
   3595         if (_private->zoomsTextOnly)
   3596             coreFrame->setPageAndTextZoomFactors(1, multiplier);
   3597         else
   3598             coreFrame->setPageAndTextZoomFactors(multiplier, 1);
   3599     }
   3600 }
   3601 
   3602 - (float)_zoomMultiplier:(BOOL)isTextOnly
   3603 {
   3604     if (isTextOnly != [self _realZoomMultiplierIsTextOnly])
   3605         return 1.0f;
   3606     return _private->zoomMultiplier;
   3607 }
   3608 
   3609 - (float)_realZoomMultiplier
   3610 {
   3611     return _private->zoomMultiplier;
   3612 }
   3613 
   3614 - (BOOL)_realZoomMultiplierIsTextOnly
   3615 {
   3616     if (!_private->page)
   3617         return NO;
   3618 
   3619     return _private->zoomsTextOnly;
   3620 }
   3621 
   3622 #define MinimumZoomMultiplier       0.5f
   3623 #define MaximumZoomMultiplier       3.0f
   3624 #define ZoomMultiplierRatio         1.2f
   3625 
   3626 - (BOOL)_canZoomOut:(BOOL)isTextOnly
   3627 {
   3628     id docView = [[[self mainFrame] frameView] documentView];
   3629     if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
   3630         id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
   3631         return [zoomingDocView _canZoomOut];
   3632     }
   3633     return [self _zoomMultiplier:isTextOnly] / ZoomMultiplierRatio > MinimumZoomMultiplier;
   3634 }
   3635 
   3636 
   3637 - (BOOL)_canZoomIn:(BOOL)isTextOnly
   3638 {
   3639     id docView = [[[self mainFrame] frameView] documentView];
   3640     if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
   3641         id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
   3642         return [zoomingDocView _canZoomIn];
   3643     }
   3644     return [self _zoomMultiplier:isTextOnly] * ZoomMultiplierRatio < MaximumZoomMultiplier;
   3645 }
   3646 
   3647 - (IBAction)_zoomOut:(id)sender isTextOnly:(BOOL)isTextOnly
   3648 {
   3649     id docView = [[[self mainFrame] frameView] documentView];
   3650     if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
   3651         id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
   3652         return [zoomingDocView _zoomOut:sender];
   3653     }
   3654     float newScale = [self _zoomMultiplier:isTextOnly] / ZoomMultiplierRatio;
   3655     if (newScale > MinimumZoomMultiplier)
   3656         [self _setZoomMultiplier:newScale isTextOnly:isTextOnly];
   3657 }
   3658 
   3659 - (IBAction)_zoomIn:(id)sender isTextOnly:(BOOL)isTextOnly
   3660 {
   3661     id docView = [[[self mainFrame] frameView] documentView];
   3662     if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
   3663         id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
   3664         return [zoomingDocView _zoomIn:sender];
   3665     }
   3666     float newScale = [self _zoomMultiplier:isTextOnly] * ZoomMultiplierRatio;
   3667     if (newScale < MaximumZoomMultiplier)
   3668         [self _setZoomMultiplier:newScale isTextOnly:isTextOnly];
   3669 }
   3670 
   3671 - (BOOL)_canResetZoom:(BOOL)isTextOnly
   3672 {
   3673     id docView = [[[self mainFrame] frameView] documentView];
   3674     if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
   3675         id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
   3676         return [zoomingDocView _canResetZoom];
   3677     }
   3678     return [self _zoomMultiplier:isTextOnly] != 1.0f;
   3679 }
   3680 
   3681 - (IBAction)_resetZoom:(id)sender isTextOnly:(BOOL)isTextOnly
   3682 {
   3683     id docView = [[[self mainFrame] frameView] documentView];
   3684     if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
   3685         id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
   3686         return [zoomingDocView _resetZoom:sender];
   3687     }
   3688     if ([self _zoomMultiplier:isTextOnly] != 1.0f)
   3689         [self _setZoomMultiplier:1.0f isTextOnly:isTextOnly];
   3690 }
   3691 
   3692 - (void)setApplicationNameForUserAgent:(NSString *)applicationName
   3693 {
   3694     NSString *name = [applicationName copy];
   3695     [_private->applicationNameForUserAgent release];
   3696     _private->applicationNameForUserAgent = name;
   3697     if (!_private->userAgentOverridden)
   3698         _private->userAgent = String();
   3699 }
   3700 
   3701 - (NSString *)applicationNameForUserAgent
   3702 {
   3703     return [[_private->applicationNameForUserAgent retain] autorelease];
   3704 }
   3705 
   3706 - (void)setCustomUserAgent:(NSString *)userAgentString
   3707 {
   3708     _private->userAgent = userAgentString;
   3709     _private->userAgentOverridden = userAgentString != nil;
   3710 }
   3711 
   3712 - (NSString *)customUserAgent
   3713 {
   3714     if (!_private->userAgentOverridden)
   3715         return nil;
   3716     return _private->userAgent;
   3717 }
   3718 
   3719 - (void)setMediaStyle:(NSString *)mediaStyle
   3720 {
   3721     if (_private->mediaStyle != mediaStyle) {
   3722         [_private->mediaStyle release];
   3723         _private->mediaStyle = [mediaStyle copy];
   3724     }
   3725 }
   3726 
   3727 - (NSString *)mediaStyle
   3728 {
   3729     return _private->mediaStyle;
   3730 }
   3731 
   3732 - (BOOL)supportsTextEncoding
   3733 {
   3734     id documentView = [[[self mainFrame] frameView] documentView];
   3735     return [documentView conformsToProtocol:@protocol(WebDocumentText)]
   3736         && [documentView supportsTextEncoding];
   3737 }
   3738 
   3739 - (void)setCustomTextEncodingName:(NSString *)encoding
   3740 {
   3741     NSString *oldEncoding = [self customTextEncodingName];
   3742     if (encoding == oldEncoding || [encoding isEqualToString:oldEncoding])
   3743         return;
   3744     if (Frame* mainFrame = [self _mainCoreFrame])
   3745         mainFrame->loader()->reloadWithOverrideEncoding(encoding);
   3746 }
   3747 
   3748 - (NSString *)_mainFrameOverrideEncoding
   3749 {
   3750     WebDataSource *dataSource = [[self mainFrame] provisionalDataSource];
   3751     if (dataSource == nil)
   3752         dataSource = [[self mainFrame] _dataSource];
   3753     if (dataSource == nil)
   3754         return nil;
   3755     return nsStringNilIfEmpty([dataSource _documentLoader]->overrideEncoding());
   3756 }
   3757 
   3758 - (NSString *)customTextEncodingName
   3759 {
   3760     return [self _mainFrameOverrideEncoding];
   3761 }
   3762 
   3763 - (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script
   3764 {
   3765     // Return statements are only valid in a function but some applications pass in scripts
   3766     // prefixed with return (<rdar://problems/5103720&4616860>) since older WebKit versions
   3767     // silently ignored the return. If the application is linked against an earlier version
   3768     // of WebKit we will strip the return so the script wont fail.
   3769     if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_JAVASCRIPT_RETURN_QUIRK)) {
   3770         NSRange returnStringRange = [script rangeOfString:@"return "];
   3771         if (returnStringRange.length && !returnStringRange.location)
   3772             script = [script substringFromIndex:returnStringRange.location + returnStringRange.length];
   3773     }
   3774 
   3775     NSString *result = [[self mainFrame] _stringByEvaluatingJavaScriptFromString:script];
   3776     // The only way stringByEvaluatingJavaScriptFromString can return nil is if the frame was removed by the script
   3777     // Since there's no way to get rid of the main frame, result will never ever be nil here.
   3778     ASSERT(result);
   3779 
   3780     return result;
   3781 }
   3782 
   3783 - (WebScriptObject *)windowScriptObject
   3784 {
   3785     Frame* coreFrame = [self _mainCoreFrame];
   3786     if (!coreFrame)
   3787         return nil;
   3788     return coreFrame->script()->windowScriptObject();
   3789 }
   3790 
   3791 // Get the appropriate user-agent string for a particular URL.
   3792 - (NSString *)userAgentForURL:(NSURL *)url
   3793 {
   3794     if (_private->useSiteSpecificSpoofing) {
   3795         // No current site-specific spoofs.
   3796     }
   3797 
   3798     if (_private->userAgent.isNull())
   3799         _private->userAgent = [[self class] _standardUserAgentWithApplicationName:_private->applicationNameForUserAgent];
   3800 
   3801     return _private->userAgent;
   3802 }
   3803 
   3804 - (void)setHostWindow:(NSWindow *)hostWindow
   3805 {
   3806     if (_private->closed && hostWindow)
   3807         return;
   3808     if (hostWindow == _private->hostWindow)
   3809         return;
   3810 
   3811     Frame* coreFrame = [self _mainCoreFrame];
   3812     if (_private->usesDocumentViews) {
   3813         for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
   3814             [[[kit(frame) frameView] documentView] viewWillMoveToHostWindow:hostWindow];
   3815     }
   3816     if (_private->hostWindow && [self window] != _private->hostWindow)
   3817         [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowWillCloseNotification object:_private->hostWindow];
   3818     if (hostWindow)
   3819         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillClose:) name:NSWindowWillCloseNotification object:hostWindow];
   3820     [_private->hostWindow release];
   3821     _private->hostWindow = [hostWindow retain];
   3822     if (_private->usesDocumentViews) {
   3823         for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
   3824             [[[kit(frame) frameView] documentView] viewDidMoveToHostWindow];
   3825     }
   3826 }
   3827 
   3828 - (NSWindow *)hostWindow
   3829 {
   3830     // -[WebView hostWindow] can sometimes be called from the WebView's [super dealloc] method
   3831     // so we check here to make sure it's not null.
   3832     if (!_private)
   3833         return nil;
   3834 
   3835     return _private->hostWindow;
   3836 }
   3837 
   3838 - (NSView <WebDocumentView> *)documentViewAtWindowPoint:(NSPoint)point
   3839 {
   3840     return [[self _frameViewAtWindowPoint:point] documentView];
   3841 }
   3842 
   3843 - (NSDictionary *)_elementAtWindowPoint:(NSPoint)windowPoint
   3844 {
   3845     WebFrameView *frameView = [self _frameViewAtWindowPoint:windowPoint];
   3846     if (!frameView)
   3847         return nil;
   3848     NSView <WebDocumentView> *documentView = [frameView documentView];
   3849     if ([documentView conformsToProtocol:@protocol(WebDocumentElement)]) {
   3850         NSPoint point = [documentView convertPoint:windowPoint fromView:nil];
   3851         return [(NSView <WebDocumentElement> *)documentView elementAtPoint:point];
   3852     }
   3853     return [NSDictionary dictionaryWithObject:[frameView webFrame] forKey:WebElementFrameKey];
   3854 }
   3855 
   3856 - (NSDictionary *)elementAtPoint:(NSPoint)point
   3857 {
   3858     return [self _elementAtWindowPoint:[self convertPoint:point toView:nil]];
   3859 }
   3860 
   3861 // The following 2 internal NSView methods are called on the drag destination to make scrolling while dragging work.
   3862 // Scrolling while dragging will only work if the drag destination is in a scroll view. The WebView is the drag destination.
   3863 // When dragging to a WebView, the document subview should scroll, but it doesn't because it is not the drag destination.
   3864 // Forward these calls to the document subview to make its scroll view scroll.
   3865 - (void)_autoscrollForDraggingInfo:(id)draggingInfo timeDelta:(NSTimeInterval)repeatDelta
   3866 {
   3867     NSView <WebDocumentView> *documentView = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
   3868     [documentView _autoscrollForDraggingInfo:draggingInfo timeDelta:repeatDelta];
   3869 }
   3870 
   3871 - (BOOL)_shouldAutoscrollForDraggingInfo:(id)draggingInfo
   3872 {
   3873     NSView <WebDocumentView> *documentView = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
   3874     return [documentView _shouldAutoscrollForDraggingInfo:draggingInfo];
   3875 }
   3876 
   3877 - (DragApplicationFlags)applicationFlags:(id <NSDraggingInfo>)draggingInfo
   3878 {
   3879     uint32_t flags = 0;
   3880     if ([NSApp modalWindow])
   3881         flags = DragApplicationIsModal;
   3882     if ([[self window] attachedSheet])
   3883         flags |= DragApplicationHasAttachedSheet;
   3884     if ([draggingInfo draggingSource] == self)
   3885         flags |= DragApplicationIsSource;
   3886     if ([[NSApp currentEvent] modifierFlags] & NSAlternateKeyMask)
   3887         flags |= DragApplicationIsCopyKeyDown;
   3888     return static_cast<DragApplicationFlags>(flags);
   3889 }
   3890 
   3891 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)draggingInfo
   3892 {
   3893     IntPoint client([draggingInfo draggingLocation]);
   3894     IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
   3895     DragData dragData(draggingInfo, client, global, static_cast<DragOperation>([draggingInfo draggingSourceOperationMask]), [self applicationFlags:draggingInfo]);
   3896     return core(self)->dragController()->dragEntered(&dragData);
   3897 }
   3898 
   3899 - (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)draggingInfo
   3900 {
   3901     Page* page = core(self);
   3902     if (!page)
   3903         return NSDragOperationNone;
   3904 
   3905     IntPoint client([draggingInfo draggingLocation]);
   3906     IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
   3907     DragData dragData(draggingInfo, client, global, static_cast<DragOperation>([draggingInfo draggingSourceOperationMask]), [self applicationFlags:draggingInfo]);
   3908     return page->dragController()->dragUpdated(&dragData);
   3909 }
   3910 
   3911 - (void)draggingExited:(id <NSDraggingInfo>)draggingInfo
   3912 {
   3913     Page* page = core(self);
   3914     if (!page)
   3915         return;
   3916 
   3917     IntPoint client([draggingInfo draggingLocation]);
   3918     IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
   3919     DragData dragData(draggingInfo, client, global, static_cast<DragOperation>([draggingInfo draggingSourceOperationMask]), [self applicationFlags:draggingInfo]);
   3920     page->dragController()->dragExited(&dragData);
   3921 }
   3922 
   3923 - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)draggingInfo
   3924 {
   3925     return YES;
   3926 }
   3927 
   3928 - (BOOL)performDragOperation:(id <NSDraggingInfo>)draggingInfo
   3929 {
   3930     IntPoint client([draggingInfo draggingLocation]);
   3931     IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
   3932     DragData dragData(draggingInfo, client, global, static_cast<DragOperation>([draggingInfo draggingSourceOperationMask]), [self applicationFlags:draggingInfo]);
   3933     return core(self)->dragController()->performDrag(&dragData);
   3934 }
   3935 
   3936 - (NSView *)_hitTest:(NSPoint *)point dragTypes:(NSSet *)types
   3937 {
   3938     NSView *hitView = [super _hitTest:point dragTypes:types];
   3939     if (!hitView && [[self superview] mouse:*point inRect:[self frame]])
   3940         return self;
   3941     return hitView;
   3942 }
   3943 
   3944 - (BOOL)acceptsFirstResponder
   3945 {
   3946     if (_private->usesDocumentViews)
   3947         return [[[self mainFrame] frameView] acceptsFirstResponder];
   3948 
   3949     // FIXME (Viewless): Need more code from WebHTMLView here.
   3950     return YES;
   3951 }
   3952 
   3953 - (BOOL)becomeFirstResponder
   3954 {
   3955     if (_private->usesDocumentViews) {
   3956         if (_private->becomingFirstResponder) {
   3957             // Fix for unrepro infinite recursion reported in Radar 4448181. If we hit this assert on
   3958             // a debug build, we should figure out what causes the problem and do a better fix.
   3959             ASSERT_NOT_REACHED();
   3960             return NO;
   3961         }
   3962 
   3963         // This works together with setNextKeyView to splice the WebView into
   3964         // the key loop similar to the way NSScrollView does this. Note that
   3965         // WebFrameView has very similar code.
   3966         NSWindow *window = [self window];
   3967         WebFrameView *mainFrameView = [[self mainFrame] frameView];
   3968 
   3969         NSResponder *previousFirstResponder = [[self window] _oldFirstResponderBeforeBecoming];
   3970         BOOL fromOutside = ![previousFirstResponder isKindOfClass:[NSView class]] || (![(NSView *)previousFirstResponder isDescendantOf:self] && previousFirstResponder != self);
   3971 
   3972         if ([window keyViewSelectionDirection] == NSSelectingPrevious) {
   3973             NSView *previousValidKeyView = [self previousValidKeyView];
   3974             if (previousValidKeyView != self && previousValidKeyView != mainFrameView) {
   3975                 _private->becomingFirstResponder = YES;
   3976                 _private->becomingFirstResponderFromOutside = fromOutside;
   3977                 [window makeFirstResponder:previousValidKeyView];
   3978                 _private->becomingFirstResponderFromOutside = NO;
   3979                 _private->becomingFirstResponder = NO;
   3980                 return YES;
   3981             }
   3982             return NO;
   3983         }
   3984 
   3985         if ([mainFrameView acceptsFirstResponder]) {
   3986             _private->becomingFirstResponder = YES;
   3987             _private->becomingFirstResponderFromOutside = fromOutside;
   3988             [window makeFirstResponder:mainFrameView];
   3989             _private->becomingFirstResponderFromOutside = NO;
   3990             _private->becomingFirstResponder = NO;
   3991             return YES;
   3992         }
   3993 
   3994         return NO;
   3995     }
   3996 
   3997     // FIXME (Viewless): Need more code from WebHTMLView here.
   3998     return YES;
   3999 }
   4000 
   4001 - (NSView *)_webcore_effectiveFirstResponder
   4002 {
   4003     if (_private && _private->usesDocumentViews) {
   4004         if (WebFrameView *frameView = [[self mainFrame] frameView])
   4005             return [frameView _webcore_effectiveFirstResponder];
   4006     }
   4007     return [super _webcore_effectiveFirstResponder];
   4008 }
   4009 
   4010 - (void)setNextKeyView:(NSView *)view
   4011 {
   4012     if (_private && _private->usesDocumentViews) {
   4013         // This works together with becomeFirstResponder to splice the WebView into
   4014         // the key loop similar to the way NSScrollView does this. Note that
   4015         // WebFrameView has similar code.
   4016         if (WebFrameView *mainFrameView = [[self mainFrame] frameView]) {
   4017             [mainFrameView setNextKeyView:view];
   4018             return;
   4019         }
   4020     }
   4021 
   4022     [super setNextKeyView:view];
   4023 }
   4024 
   4025 static WebFrame *incrementFrame(WebFrame *frame, WebFindOptions options = 0)
   4026 {
   4027     Frame* coreFrame = core(frame);
   4028     return kit((options & WebFindOptionsBackwards)
   4029         ? coreFrame->tree()->traversePreviousWithWrap(options & WebFindOptionsWrapAround)
   4030         : coreFrame->tree()->traverseNextWithWrap(options & WebFindOptionsWrapAround));
   4031 }
   4032 
   4033 - (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag
   4034 {
   4035     return [self searchFor:string direction:forward caseSensitive:caseFlag wrap:wrapFlag startInSelection:NO];
   4036 }
   4037 
   4038 + (void)registerViewClass:(Class)viewClass representationClass:(Class)representationClass forMIMEType:(NSString *)MIMEType
   4039 {
   4040     [[WebFrameView _viewTypesAllowImageTypeOmission:YES] setObject:viewClass forKey:MIMEType];
   4041     [[WebDataSource _repTypesAllowImageTypeOmission:YES] setObject:representationClass forKey:MIMEType];
   4042 
   4043     // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
   4044     // in the WebCore MIMEType registry.  For now we're doing this in a safe, limited manner
   4045     // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
   4046     if ([viewClass class] == [WebHTMLView class])
   4047         MIMETypeRegistry::getSupportedNonImageMIMETypes().add(MIMEType);
   4048 }
   4049 
   4050 - (void)setGroupName:(NSString *)groupName
   4051 {
   4052     if (!_private->page)
   4053         return;
   4054     _private->page->setGroupName(groupName);
   4055 }
   4056 
   4057 - (NSString *)groupName
   4058 {
   4059     if (!_private->page)
   4060         return nil;
   4061     return _private->page->groupName();
   4062 }
   4063 
   4064 - (double)estimatedProgress
   4065 {
   4066     if (!_private->page)
   4067         return 0.0;
   4068     return _private->page->progress()->estimatedProgress();
   4069 }
   4070 
   4071 - (NSArray *)pasteboardTypesForSelection
   4072 {
   4073     NSView <WebDocumentView> *documentView = [[[self _selectedOrMainFrame] frameView] documentView];
   4074     if ([documentView conformsToProtocol:@protocol(WebDocumentSelection)]) {
   4075         return [(NSView <WebDocumentSelection> *)documentView pasteboardTypesForSelection];
   4076     }
   4077     return [NSArray array];
   4078 }
   4079 
   4080 - (void)writeSelectionWithPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
   4081 {
   4082     WebFrame *frame = [self _selectedOrMainFrame];
   4083     if (frame && [frame _hasSelection]) {
   4084         NSView <WebDocumentView> *documentView = [[frame frameView] documentView];
   4085         if ([documentView conformsToProtocol:@protocol(WebDocumentSelection)])
   4086             [(NSView <WebDocumentSelection> *)documentView writeSelectionWithPasteboardTypes:types toPasteboard:pasteboard];
   4087     }
   4088 }
   4089 
   4090 - (NSArray *)pasteboardTypesForElement:(NSDictionary *)element
   4091 {
   4092     if ([element objectForKey:WebElementImageURLKey] != nil) {
   4093         return [NSPasteboard _web_writableTypesForImageIncludingArchive:([element objectForKey:WebElementDOMNodeKey] != nil)];
   4094     } else if ([element objectForKey:WebElementLinkURLKey] != nil) {
   4095         return [NSPasteboard _web_writableTypesForURL];
   4096     } else if ([[element objectForKey:WebElementIsSelectedKey] boolValue]) {
   4097         return [self pasteboardTypesForSelection];
   4098     }
   4099     return [NSArray array];
   4100 }
   4101 
   4102 - (void)writeElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
   4103 {
   4104     if ([element objectForKey:WebElementImageURLKey] != nil) {
   4105         [self _writeImageForElement:element withPasteboardTypes:types toPasteboard:pasteboard];
   4106     } else if ([element objectForKey:WebElementLinkURLKey] != nil) {
   4107         [self _writeLinkElement:element withPasteboardTypes:types toPasteboard:pasteboard];
   4108     } else if ([[element objectForKey:WebElementIsSelectedKey] boolValue]) {
   4109         [self writeSelectionWithPasteboardTypes:types toPasteboard:pasteboard];
   4110     }
   4111 }
   4112 
   4113 - (void)moveDragCaretToPoint:(NSPoint)point
   4114 {
   4115     if (Page* page = core(self))
   4116         page->dragController()->placeDragCaret(IntPoint([self convertPoint:point toView:nil]));
   4117 }
   4118 
   4119 - (void)removeDragCaret
   4120 {
   4121     if (Page* page = core(self))
   4122         page->dragController()->dragEnded();
   4123 }
   4124 
   4125 - (void)setMainFrameURL:(NSString *)URLString
   4126 {
   4127     [[self mainFrame] loadRequest: [NSURLRequest requestWithURL: [NSURL _web_URLWithDataAsString: URLString]]];
   4128 }
   4129 
   4130 - (NSString *)mainFrameURL
   4131 {
   4132     WebDataSource *ds;
   4133     ds = [[self mainFrame] provisionalDataSource];
   4134     if (!ds)
   4135         ds = [[self mainFrame] _dataSource];
   4136     return [[[ds request] URL] _web_originalDataAsString];
   4137 }
   4138 
   4139 - (BOOL)isLoading
   4140 {
   4141     LOG (Bindings, "isLoading = %d", (int)[self _isLoading]);
   4142     return [self _isLoading];
   4143 }
   4144 
   4145 - (NSString *)mainFrameTitle
   4146 {
   4147     NSString *mainFrameTitle = [[[self mainFrame] _dataSource] pageTitle];
   4148     return (mainFrameTitle != nil) ? mainFrameTitle : (NSString *)@"";
   4149 }
   4150 
   4151 - (NSImage *)mainFrameIcon
   4152 {
   4153     return [[WebIconDatabase sharedIconDatabase] iconForURL:[[[[self mainFrame] _dataSource] _URL] _web_originalDataAsString] withSize:WebIconSmallSize];
   4154 }
   4155 
   4156 - (DOMDocument *)mainFrameDocument
   4157 {
   4158     // only return the actual value if the state we're in gives NSTreeController
   4159     // enough time to release its observers on the old model
   4160     if (_private->mainFrameDocumentReady)
   4161         return [[self mainFrame] DOMDocument];
   4162     return nil;
   4163 }
   4164 
   4165 - (void)setDrawsBackground:(BOOL)drawsBackground
   4166 {
   4167     if (_private->drawsBackground == drawsBackground)
   4168         return;
   4169     _private->drawsBackground = drawsBackground;
   4170     [[self mainFrame] _updateBackgroundAndUpdatesWhileOffscreen];
   4171 }
   4172 
   4173 - (BOOL)drawsBackground
   4174 {
   4175     // This method can be called beneath -[NSView dealloc] after we have cleared _private,
   4176     // indirectly via -[WebFrameView viewDidMoveToWindow].
   4177     return !_private || _private->drawsBackground;
   4178 }
   4179 
   4180 - (void)setShouldUpdateWhileOffscreen:(BOOL)updateWhileOffscreen
   4181 {
   4182     if (_private->shouldUpdateWhileOffscreen == updateWhileOffscreen)
   4183         return;
   4184     _private->shouldUpdateWhileOffscreen = updateWhileOffscreen;
   4185     [[self mainFrame] _updateBackgroundAndUpdatesWhileOffscreen];
   4186 }
   4187 
   4188 - (BOOL)shouldUpdateWhileOffscreen
   4189 {
   4190     return _private->shouldUpdateWhileOffscreen;
   4191 }
   4192 
   4193 - (void)setCurrentNodeHighlight:(WebNodeHighlight *)nodeHighlight
   4194 {
   4195     id old = _private->currentNodeHighlight;
   4196     _private->currentNodeHighlight = [nodeHighlight retain];
   4197     [old release];
   4198 }
   4199 
   4200 - (WebNodeHighlight *)currentNodeHighlight
   4201 {
   4202     return _private->currentNodeHighlight;
   4203 }
   4204 
   4205 - (NSView *)previousValidKeyView
   4206 {
   4207     NSView *result = [super previousValidKeyView];
   4208 
   4209     // Work around AppKit bug 6905484. If the result is a view that's inside this one, it's
   4210     // possible it is the wrong answer, because the fact that it's a descendant causes the
   4211     // code that implements key view redirection to fail; this means we won't redirect to
   4212     // the toolbar, for example, when we hit the edge of a window. Since the bug is specific
   4213     // to cases where the receiver of previousValidKeyView is an ancestor of the last valid
   4214     // key view in the loop, we can sidestep it by walking along previous key views until
   4215     // we find one that is not a superview, then using that to call previousValidKeyView.
   4216 
   4217     if (![result isDescendantOf:self])
   4218         return result;
   4219 
   4220     // Use a visited set so we don't loop indefinitely when walking crazy key loops.
   4221     // AppKit uses such sets internally and we want our loop to be as robust as its loops.
   4222     RetainPtr<CFMutableSetRef> visitedViews = CFSetCreateMutable(0, 0, 0);
   4223     CFSetAddValue(visitedViews.get(), result);
   4224 
   4225     NSView *previousView = self;
   4226     do {
   4227         CFSetAddValue(visitedViews.get(), previousView);
   4228         previousView = [previousView previousKeyView];
   4229         if (!previousView || CFSetGetValue(visitedViews.get(), previousView))
   4230             return result;
   4231     } while ([result isDescendantOf:previousView]);
   4232     return [previousView previousValidKeyView];
   4233 }
   4234 
   4235 @end
   4236 
   4237 @implementation WebView (WebIBActions)
   4238 
   4239 - (IBAction)takeStringURLFrom: sender
   4240 {
   4241     NSString *URLString = [sender stringValue];
   4242 
   4243     [[self mainFrame] loadRequest: [NSURLRequest requestWithURL: [NSURL _web_URLWithDataAsString: URLString]]];
   4244 }
   4245 
   4246 - (BOOL)canGoBack
   4247 {
   4248     if (!_private->page || _private->page->defersLoading())
   4249         return NO;
   4250 
   4251     return !!_private->page->backForwardList()->backItem();
   4252 }
   4253 
   4254 - (BOOL)canGoForward
   4255 {
   4256     if (!_private->page || _private->page->defersLoading())
   4257         return NO;
   4258 
   4259     return !!_private->page->backForwardList()->forwardItem();
   4260 }
   4261 
   4262 - (IBAction)goBack:(id)sender
   4263 {
   4264     [self goBack];
   4265 }
   4266 
   4267 - (IBAction)goForward:(id)sender
   4268 {
   4269     [self goForward];
   4270 }
   4271 
   4272 - (IBAction)stopLoading:(id)sender
   4273 {
   4274     [[self mainFrame] stopLoading];
   4275 }
   4276 
   4277 - (IBAction)reload:(id)sender
   4278 {
   4279     [[self mainFrame] reload];
   4280 }
   4281 
   4282 - (IBAction)reloadFromOrigin:(id)sender
   4283 {
   4284     [[self mainFrame] reloadFromOrigin];
   4285 }
   4286 
   4287 // FIXME: This code should move into WebCore so that it is not duplicated in each WebKit.
   4288 // (This includes canMakeTextSmaller/Larger, makeTextSmaller/Larger, and canMakeTextStandardSize/makeTextStandardSize)
   4289 - (BOOL)canMakeTextSmaller
   4290 {
   4291     return [self _canZoomOut:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
   4292 }
   4293 
   4294 - (IBAction)makeTextSmaller:(id)sender
   4295 {
   4296     return [self _zoomOut:sender isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
   4297 }
   4298 
   4299 - (BOOL)canMakeTextLarger
   4300 {
   4301     return [self _canZoomIn:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
   4302 }
   4303 
   4304 - (IBAction)makeTextLarger:(id)sender
   4305 {
   4306     return [self _zoomIn:sender isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
   4307 }
   4308 
   4309 - (BOOL)canMakeTextStandardSize
   4310 {
   4311     return [self _canResetZoom:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
   4312 }
   4313 
   4314 - (IBAction)makeTextStandardSize:(id)sender
   4315 {
   4316    return [self _resetZoom:sender isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
   4317 }
   4318 
   4319 - (IBAction)toggleSmartInsertDelete:(id)sender
   4320 {
   4321     [self setSmartInsertDeleteEnabled:![self smartInsertDeleteEnabled]];
   4322 }
   4323 
   4324 - (IBAction)toggleContinuousSpellChecking:(id)sender
   4325 {
   4326     [self setContinuousSpellCheckingEnabled:![self isContinuousSpellCheckingEnabled]];
   4327 }
   4328 
   4329 - (BOOL)_responderValidateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item
   4330 {
   4331     id responder = [self _responderForResponderOperations];
   4332     if (responder != self && [responder respondsToSelector:[item action]]) {
   4333         if ([responder respondsToSelector:@selector(validateUserInterfaceItemWithoutDelegate:)])
   4334             return [responder validateUserInterfaceItemWithoutDelegate:item];
   4335         if ([responder respondsToSelector:@selector(validateUserInterfaceItem:)])
   4336             return [responder validateUserInterfaceItem:item];
   4337         return YES;
   4338     }
   4339     return NO;
   4340 }
   4341 
   4342 #define VALIDATE(name) \
   4343     else if (action == @selector(name:)) { return [self _responderValidateUserInterfaceItem:item]; }
   4344 
   4345 - (BOOL)validateUserInterfaceItemWithoutDelegate:(id <NSValidatedUserInterfaceItem>)item
   4346 {
   4347     SEL action = [item action];
   4348 
   4349     if (action == @selector(goBack:)) {
   4350         return [self canGoBack];
   4351     } else if (action == @selector(goForward:)) {
   4352         return [self canGoForward];
   4353     } else if (action == @selector(makeTextLarger:)) {
   4354         return [self canMakeTextLarger];
   4355     } else if (action == @selector(makeTextSmaller:)) {
   4356         return [self canMakeTextSmaller];
   4357     } else if (action == @selector(makeTextStandardSize:)) {
   4358         return [self canMakeTextStandardSize];
   4359     } else if (action == @selector(reload:)) {
   4360         return [[self mainFrame] _dataSource] != nil;
   4361     } else if (action == @selector(stopLoading:)) {
   4362         return [self _isLoading];
   4363     } else if (action == @selector(toggleContinuousSpellChecking:)) {
   4364         BOOL checkMark = NO;
   4365         BOOL retVal = NO;
   4366         if ([self _continuousCheckingAllowed]) {
   4367             checkMark = [self isContinuousSpellCheckingEnabled];
   4368             retVal = YES;
   4369         }
   4370         if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
   4371             NSMenuItem *menuItem = (NSMenuItem *)item;
   4372             [menuItem setState:checkMark ? NSOnState : NSOffState];
   4373         }
   4374         return retVal;
   4375     } else if (action == @selector(toggleSmartInsertDelete:)) {
   4376         BOOL checkMark = [self smartInsertDeleteEnabled];
   4377         if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
   4378             NSMenuItem *menuItem = (NSMenuItem *)item;
   4379             [menuItem setState:checkMark ? NSOnState : NSOffState];
   4380         }
   4381         return YES;
   4382 #ifndef BUILDING_ON_TIGER
   4383     } else if (action == @selector(toggleGrammarChecking:)) {
   4384         BOOL checkMark = [self isGrammarCheckingEnabled];
   4385         if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
   4386             NSMenuItem *menuItem = (NSMenuItem *)item;
   4387             [menuItem setState:checkMark ? NSOnState : NSOffState];
   4388         }
   4389         return YES;
   4390 #endif
   4391 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
   4392     } else if (action == @selector(toggleAutomaticQuoteSubstitution:)) {
   4393         BOOL checkMark = [self isAutomaticQuoteSubstitutionEnabled];
   4394         if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
   4395             NSMenuItem *menuItem = (NSMenuItem *)item;
   4396             [menuItem setState:checkMark ? NSOnState : NSOffState];
   4397         }
   4398         return YES;
   4399     } else if (action == @selector(toggleAutomaticLinkDetection:)) {
   4400         BOOL checkMark = [self isAutomaticLinkDetectionEnabled];
   4401         if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
   4402             NSMenuItem *menuItem = (NSMenuItem *)item;
   4403             [menuItem setState:checkMark ? NSOnState : NSOffState];
   4404         }
   4405         return YES;
   4406     } else if (action == @selector(toggleAutomaticDashSubstitution:)) {
   4407         BOOL checkMark = [self isAutomaticDashSubstitutionEnabled];
   4408         if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
   4409             NSMenuItem *menuItem = (NSMenuItem *)item;
   4410             [menuItem setState:checkMark ? NSOnState : NSOffState];
   4411         }
   4412         return YES;
   4413     } else if (action == @selector(toggleAutomaticTextReplacement:)) {
   4414         BOOL checkMark = [self isAutomaticTextReplacementEnabled];
   4415         if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
   4416             NSMenuItem *menuItem = (NSMenuItem *)item;
   4417             [menuItem setState:checkMark ? NSOnState : NSOffState];
   4418         }
   4419         return YES;
   4420     } else if (action == @selector(toggleAutomaticSpellingCorrection:)) {
   4421         BOOL checkMark = [self isAutomaticSpellingCorrectionEnabled];
   4422         if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
   4423             NSMenuItem *menuItem = (NSMenuItem *)item;
   4424             [menuItem setState:checkMark ? NSOnState : NSOffState];
   4425         }
   4426         return YES;
   4427 #endif
   4428     }
   4429     FOR_EACH_RESPONDER_SELECTOR(VALIDATE)
   4430 
   4431     return YES;
   4432 }
   4433 
   4434 - (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item
   4435 {
   4436     BOOL result = [self validateUserInterfaceItemWithoutDelegate:item];
   4437     return CallUIDelegateReturningBoolean(result, self, @selector(webView:validateUserInterfaceItem:defaultValidation:), item, result);
   4438 }
   4439 
   4440 @end
   4441 
   4442 @implementation WebView (WebPendingPublic)
   4443 
   4444 - (void)scheduleInRunLoop:(NSRunLoop *)runLoop forMode:(NSString *)mode
   4445 {
   4446     if (runLoop && mode)
   4447         core(self)->addSchedulePair(SchedulePair::create(runLoop, (CFStringRef)mode));
   4448 }
   4449 
   4450 - (void)unscheduleFromRunLoop:(NSRunLoop *)runLoop forMode:(NSString *)mode
   4451 {
   4452     if (runLoop && mode)
   4453         core(self)->removeSchedulePair(SchedulePair::create(runLoop, (CFStringRef)mode));
   4454 }
   4455 
   4456 static BOOL findString(NSView <WebDocumentSearching> *searchView, NSString *string, WebFindOptions options)
   4457 {
   4458     if ([searchView conformsToProtocol:@protocol(WebDocumentOptionsSearching)])
   4459         return [(NSView <WebDocumentOptionsSearching> *)searchView _findString:string options:options];
   4460     if ([searchView conformsToProtocol:@protocol(WebDocumentIncrementalSearching)])
   4461         return [(NSView <WebDocumentIncrementalSearching> *)searchView searchFor:string direction:!(options & WebFindOptionsBackwards) caseSensitive:!(options & WebFindOptionsCaseInsensitive) wrap:!!(options & WebFindOptionsWrapAround) startInSelection:!!(options & WebFindOptionsStartInSelection)];
   4462     return [searchView searchFor:string direction:!(options & WebFindOptionsBackwards) caseSensitive:!(options & WebFindOptionsCaseInsensitive) wrap:!!(options & WebFindOptionsWrapAround)];
   4463 }
   4464 
   4465 - (BOOL)findString:(NSString *)string options:(WebFindOptions)options
   4466 {
   4467     if (_private->closed)
   4468         return NO;
   4469 
   4470     // Get the frame holding the selection, or start with the main frame
   4471     WebFrame *startFrame = [self _selectedOrMainFrame];
   4472 
   4473     // Search the first frame, then all the other frames, in order
   4474     NSView <WebDocumentSearching> *startSearchView = nil;
   4475     WebFrame *frame = startFrame;
   4476     do {
   4477         WebFrame *nextFrame = incrementFrame(frame, options);
   4478 
   4479         BOOL onlyOneFrame = (frame == nextFrame);
   4480         ASSERT(!onlyOneFrame || frame == startFrame);
   4481 
   4482         id <WebDocumentView> view = [[frame frameView] documentView];
   4483         if ([view conformsToProtocol:@protocol(WebDocumentSearching)]) {
   4484             NSView <WebDocumentSearching> *searchView = (NSView <WebDocumentSearching> *)view;
   4485 
   4486             if (frame == startFrame)
   4487                 startSearchView = searchView;
   4488 
   4489             // In some cases we have to search some content twice; see comment later in this method.
   4490             // We can avoid ever doing this in the common one-frame case by passing the wrap option through
   4491             // here, and then bailing out before we get to the code that would search again in the
   4492             // same content.
   4493             WebFindOptions optionsForThisPass = onlyOneFrame ? options : (options & ~WebFindOptionsWrapAround);
   4494 
   4495             if (findString(searchView, string, optionsForThisPass)) {
   4496                 if (frame != startFrame)
   4497                     [startFrame _clearSelection];
   4498                 [[self window] makeFirstResponder:searchView];
   4499                 return YES;
   4500             }
   4501 
   4502             if (onlyOneFrame)
   4503                 return NO;
   4504         }
   4505         frame = nextFrame;
   4506     } while (frame && frame != startFrame);
   4507 
   4508     // If there are multiple frames and WebFindOptionsWrapAround is set and we've visited each one without finding a result, we still need to search in the
   4509     // 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
   4510     // way to make sure the entire frame is searched is to pass WebFindOptionsWrapAround. When there are no matches, this will search
   4511     // some content that we already searched on the first pass. In the worst case, we could search the entire contents of this frame twice.
   4512     // To fix this, we'd need to add a mechanism to specify a range in which to search.
   4513     if ((options & WebFindOptionsWrapAround) && startSearchView) {
   4514         if (findString(startSearchView, string, options)) {
   4515             [[self window] makeFirstResponder:startSearchView];
   4516             return YES;
   4517         }
   4518     }
   4519     return NO;
   4520 }
   4521 
   4522 - (void)setHoverFeedbackSuspended:(BOOL)newValue
   4523 {
   4524     if (_private->hoverFeedbackSuspended == newValue)
   4525         return;
   4526 
   4527     _private->hoverFeedbackSuspended = newValue;
   4528 
   4529     if (_private->usesDocumentViews) {
   4530         id <WebDocumentView> documentView = [[[self mainFrame] frameView] documentView];
   4531         // FIXME: in a perfect world we'd do this in a general way that worked with any document view,
   4532         // such as by calling a protocol method or using respondsToSelector or sending a notification.
   4533         // But until there is any need for these more general solutions, we'll just hardwire it to work
   4534         // with WebHTMLView.
   4535         // Note that _hoverFeedbackSuspendedChanged needs to be called only on the main WebHTMLView, not
   4536         // on each subframe separately.
   4537         if ([documentView isKindOfClass:[WebHTMLView class]])
   4538             [(WebHTMLView *)documentView _hoverFeedbackSuspendedChanged];
   4539         return;
   4540     }
   4541 
   4542     [self _updateMouseoverWithFakeEvent];
   4543 }
   4544 
   4545 - (BOOL)isHoverFeedbackSuspended
   4546 {
   4547     return _private->hoverFeedbackSuspended;
   4548 }
   4549 
   4550 - (void)setMainFrameDocumentReady:(BOOL)mainFrameDocumentReady
   4551 {
   4552     // by setting this to NO, calls to mainFrameDocument are forced to return nil
   4553     // setting this to YES lets it return the actual DOMDocument value
   4554     // we use this to tell NSTreeController to reset its observers and clear its state
   4555     if (_private->mainFrameDocumentReady == mainFrameDocumentReady)
   4556         return;
   4557     [self _willChangeValueForKey:_WebMainFrameDocumentKey];
   4558     _private->mainFrameDocumentReady = mainFrameDocumentReady;
   4559     [self _didChangeValueForKey:_WebMainFrameDocumentKey];
   4560     // this will cause observers to call mainFrameDocument where this flag will be checked
   4561 }
   4562 
   4563 // This method name is used by Mail on Tiger (but not post-Tiger), so we shouldn't delete it
   4564 // until the day comes when we're no longer supporting Mail on Tiger.
   4565 - (WebFrame *)_frameForCurrentSelection
   4566 {
   4567     return [self _selectedOrMainFrame];
   4568 }
   4569 
   4570 - (void)setTabKeyCyclesThroughElements:(BOOL)cyclesElements
   4571 {
   4572     _private->tabKeyCyclesThroughElementsChanged = YES;
   4573     if (_private->page)
   4574         _private->page->setTabKeyCyclesThroughElements(cyclesElements);
   4575 }
   4576 
   4577 - (BOOL)tabKeyCyclesThroughElements
   4578 {
   4579     return _private->page && _private->page->tabKeyCyclesThroughElements();
   4580 }
   4581 
   4582 - (void)setScriptDebugDelegate:(id)delegate
   4583 {
   4584     _private->scriptDebugDelegate = delegate;
   4585     [self _cacheScriptDebugDelegateImplementations];
   4586 
   4587     if (delegate)
   4588         [self _attachScriptDebuggerToAllFrames];
   4589     else
   4590         [self _detachScriptDebuggerFromAllFrames];
   4591 }
   4592 
   4593 - (id)scriptDebugDelegate
   4594 {
   4595     return _private->scriptDebugDelegate;
   4596 }
   4597 
   4598 - (void)setHistoryDelegate:(id)delegate
   4599 {
   4600     _private->historyDelegate = delegate;
   4601     [self _cacheHistoryDelegateImplementations];
   4602 }
   4603 
   4604 - (id)historyDelegate
   4605 {
   4606     return _private->historyDelegate;
   4607 }
   4608 
   4609 - (BOOL)shouldClose
   4610 {
   4611     Frame* coreFrame = [self _mainCoreFrame];
   4612     if (!coreFrame)
   4613         return YES;
   4614     return coreFrame->loader()->shouldClose();
   4615 }
   4616 
   4617 static NSAppleEventDescriptor* aeDescFromJSValue(ExecState* exec, JSValue jsValue)
   4618 {
   4619     NSAppleEventDescriptor* aeDesc = 0;
   4620     if (jsValue.isBoolean())
   4621         return [NSAppleEventDescriptor descriptorWithBoolean:jsValue.getBoolean()];
   4622     if (jsValue.isString())
   4623         return [NSAppleEventDescriptor descriptorWithString:ustringToString(jsValue.getString(exec))];
   4624     if (jsValue.isNumber()) {
   4625         double value = jsValue.uncheckedGetNumber();
   4626         int intValue = value;
   4627         if (value == intValue)
   4628             return [NSAppleEventDescriptor descriptorWithDescriptorType:typeSInt32 bytes:&intValue length:sizeof(intValue)];
   4629         return [NSAppleEventDescriptor descriptorWithDescriptorType:typeIEEE64BitFloatingPoint bytes:&value length:sizeof(value)];
   4630     }
   4631     if (jsValue.isObject()) {
   4632         JSObject* object = jsValue.getObject();
   4633         if (object->inherits(&DateInstance::s_info)) {
   4634             DateInstance* date = static_cast<DateInstance*>(object);
   4635             double ms = date->internalNumber();
   4636             if (!isnan(ms)) {
   4637                 CFAbsoluteTime utcSeconds = ms / 1000 - kCFAbsoluteTimeIntervalSince1970;
   4638                 LongDateTime ldt;
   4639                 if (noErr == UCConvertCFAbsoluteTimeToLongDateTime(utcSeconds, &ldt))
   4640                     return [NSAppleEventDescriptor descriptorWithDescriptorType:typeLongDateTime bytes:&ldt length:sizeof(ldt)];
   4641             }
   4642         }
   4643         else if (object->inherits(&JSArray::s_info)) {
   4644             DEFINE_STATIC_LOCAL(HashSet<JSObject*>, visitedElems, ());
   4645             if (!visitedElems.contains(object)) {
   4646                 visitedElems.add(object);
   4647 
   4648                 JSArray* array = static_cast<JSArray*>(object);
   4649                 aeDesc = [NSAppleEventDescriptor listDescriptor];
   4650                 unsigned numItems = array->length();
   4651                 for (unsigned i = 0; i < numItems; ++i)
   4652                     [aeDesc insertDescriptor:aeDescFromJSValue(exec, array->get(exec, i)) atIndex:0];
   4653 
   4654                 visitedElems.remove(object);
   4655                 return aeDesc;
   4656             }
   4657         }
   4658         JSValue primitive = object->toPrimitive(exec);
   4659         if (exec->hadException()) {
   4660             exec->clearException();
   4661             return [NSAppleEventDescriptor nullDescriptor];
   4662         }
   4663         return aeDescFromJSValue(exec, primitive);
   4664     }
   4665     if (jsValue.isUndefined())
   4666         return [NSAppleEventDescriptor descriptorWithTypeCode:cMissingValue];
   4667     ASSERT(jsValue.isNull());
   4668     return [NSAppleEventDescriptor nullDescriptor];
   4669 }
   4670 
   4671 - (NSAppleEventDescriptor *)aeDescByEvaluatingJavaScriptFromString:(NSString *)script
   4672 {
   4673     Frame* coreFrame = [self _mainCoreFrame];
   4674     if (!coreFrame)
   4675         return nil;
   4676     if (!coreFrame->document())
   4677         return nil;
   4678     JSValue result = coreFrame->script()->executeScript(script, true).jsValue();
   4679     if (!result) // FIXME: pass errors
   4680         return 0;
   4681     JSLock lock(SilenceAssertionsOnly);
   4682     return aeDescFromJSValue(coreFrame->script()->globalObject(mainThreadNormalWorld())->globalExec(), result);
   4683 }
   4684 
   4685 - (BOOL)canMarkAllTextMatches
   4686 {
   4687     if (_private->closed)
   4688         return NO;
   4689 
   4690     WebFrame *frame = [self mainFrame];
   4691     do {
   4692         id <WebDocumentView> view = [[frame frameView] documentView];
   4693         if (view && ![view conformsToProtocol:@protocol(WebMultipleTextMatches)])
   4694             return NO;
   4695 
   4696         frame = incrementFrame(frame);
   4697     } while (frame);
   4698 
   4699     return YES;
   4700 }
   4701 
   4702 - (NSUInteger)countMatchesForText:(NSString *)string options:(WebFindOptions)options highlight:(BOOL)highlight limit:(NSUInteger)limit markMatches:(BOOL)markMatches
   4703 {
   4704     return [self countMatchesForText:string inDOMRange:nil options:options highlight:highlight limit:limit markMatches:markMatches];
   4705 }
   4706 
   4707 - (NSUInteger)countMatchesForText:(NSString *)string inDOMRange:(DOMRange *)range options:(WebFindOptions)options highlight:(BOOL)highlight limit:(NSUInteger)limit markMatches:(BOOL)markMatches
   4708 {
   4709     if (_private->closed)
   4710         return 0;
   4711 
   4712     WebFrame *frame = [self mainFrame];
   4713     unsigned matchCount = 0;
   4714     do {
   4715         id <WebDocumentView> view = [[frame frameView] documentView];
   4716         if ([view conformsToProtocol:@protocol(WebMultipleTextMatches)]) {
   4717             if (markMatches)
   4718                 [(NSView <WebMultipleTextMatches>*)view setMarkedTextMatchesAreHighlighted:highlight];
   4719 
   4720             ASSERT(limit == 0 || matchCount < limit);
   4721             matchCount += [(NSView <WebMultipleTextMatches>*)view countMatchesForText:string inDOMRange:range options:options limit:(limit == 0 ? 0 : limit - matchCount) markMatches:markMatches];
   4722 
   4723             // Stop looking if we've reached the limit. A limit of 0 means no limit.
   4724             if (limit > 0 && matchCount >= limit)
   4725                 break;
   4726         }
   4727 
   4728         frame = incrementFrame(frame);
   4729     } while (frame);
   4730 
   4731     return matchCount;
   4732 }
   4733 
   4734 - (void)unmarkAllTextMatches
   4735 {
   4736     if (_private->closed)
   4737         return;
   4738 
   4739     WebFrame *frame = [self mainFrame];
   4740     do {
   4741         id <WebDocumentView> view = [[frame frameView] documentView];
   4742         if ([view conformsToProtocol:@protocol(WebMultipleTextMatches)])
   4743             [(NSView <WebMultipleTextMatches>*)view unmarkAllTextMatches];
   4744 
   4745         frame = incrementFrame(frame);
   4746     } while (frame);
   4747 }
   4748 
   4749 - (NSArray *)rectsForTextMatches
   4750 {
   4751     if (_private->closed)
   4752         return [NSArray array];
   4753 
   4754     NSMutableArray *result = [NSMutableArray array];
   4755     WebFrame *frame = [self mainFrame];
   4756     do {
   4757         id <WebDocumentView> view = [[frame frameView] documentView];
   4758         if ([view conformsToProtocol:@protocol(WebMultipleTextMatches)]) {
   4759             NSView <WebMultipleTextMatches> *documentView = (NSView <WebMultipleTextMatches> *)view;
   4760             NSRect documentViewVisibleRect = [documentView visibleRect];
   4761             NSArray *originalRects = [documentView rectsForTextMatches];
   4762             unsigned rectCount = [originalRects count];
   4763             unsigned rectIndex;
   4764             NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
   4765             for (rectIndex = 0; rectIndex < rectCount; ++rectIndex) {
   4766                 NSRect r = [[originalRects objectAtIndex:rectIndex] rectValue];
   4767                 // Clip rect to document view's visible rect so rect is confined to subframe
   4768                 r = NSIntersectionRect(r, documentViewVisibleRect);
   4769                 if (NSIsEmptyRect(r))
   4770                     continue;
   4771 
   4772                 // Convert rect to our coordinate system
   4773                 r = [documentView convertRect:r toView:self];
   4774                 [result addObject:[NSValue valueWithRect:r]];
   4775                 if (rectIndex % 10 == 0) {
   4776                     [pool drain];
   4777                     pool = [[NSAutoreleasePool alloc] init];
   4778                 }
   4779             }
   4780             [pool drain];
   4781         }
   4782 
   4783         frame = incrementFrame(frame);
   4784     } while (frame);
   4785 
   4786     return result;
   4787 }
   4788 
   4789 - (void)scrollDOMRangeToVisible:(DOMRange *)range
   4790 {
   4791     [[[[range startContainer] ownerDocument] webFrame] _scrollDOMRangeToVisible:range];
   4792 }
   4793 
   4794 - (BOOL)allowsUndo
   4795 {
   4796     return _private->allowsUndo;
   4797 }
   4798 
   4799 - (void)setAllowsUndo:(BOOL)flag
   4800 {
   4801     _private->allowsUndo = flag;
   4802 }
   4803 
   4804 - (void)setPageSizeMultiplier:(float)m
   4805 {
   4806     [self _setZoomMultiplier:m isTextOnly:NO];
   4807 }
   4808 
   4809 - (float)pageSizeMultiplier
   4810 {
   4811     return ![self _realZoomMultiplierIsTextOnly] ? _private->zoomMultiplier : 1.0f;
   4812 }
   4813 
   4814 - (BOOL)canZoomPageIn
   4815 {
   4816     return [self _canZoomIn:NO];
   4817 }
   4818 
   4819 - (IBAction)zoomPageIn:(id)sender
   4820 {
   4821     return [self _zoomIn:sender isTextOnly:NO];
   4822 }
   4823 
   4824 - (BOOL)canZoomPageOut
   4825 {
   4826     return [self _canZoomOut:NO];
   4827 }
   4828 
   4829 - (IBAction)zoomPageOut:(id)sender
   4830 {
   4831     return [self _zoomOut:sender isTextOnly:NO];
   4832 }
   4833 
   4834 - (BOOL)canResetPageZoom
   4835 {
   4836     return [self _canResetZoom:NO];
   4837 }
   4838 
   4839 - (IBAction)resetPageZoom:(id)sender
   4840 {
   4841     return [self _resetZoom:sender isTextOnly:NO];
   4842 }
   4843 
   4844 - (void)setMediaVolume:(float)volume
   4845 {
   4846     if (_private->page)
   4847         _private->page->setMediaVolume(volume);
   4848 }
   4849 
   4850 - (float)mediaVolume
   4851 {
   4852     if (!_private->page)
   4853         return 0;
   4854 
   4855     return _private->page->mediaVolume();
   4856 }
   4857 
   4858 - (void)addVisitedLinks:(NSArray *)visitedLinks
   4859 {
   4860     PageGroup& group = core(self)->group();
   4861 
   4862     NSEnumerator *enumerator = [visitedLinks objectEnumerator];
   4863     while (NSString *url = [enumerator nextObject]) {
   4864         size_t length = [url length];
   4865         const UChar* characters = CFStringGetCharactersPtr(reinterpret_cast<CFStringRef>(url));
   4866         if (characters)
   4867             group.addVisitedLink(characters, length);
   4868         else {
   4869             Vector<UChar, 512> buffer(length);
   4870             [url getCharacters:buffer.data()];
   4871             group.addVisitedLink(buffer.data(), length);
   4872         }
   4873     }
   4874 }
   4875 
   4876 @end
   4877 
   4878 @implementation WebView (WebViewPrintingPrivate)
   4879 
   4880 - (float)_headerHeight
   4881 {
   4882     return CallUIDelegateReturningFloat(self, @selector(webViewHeaderHeight:));
   4883 }
   4884 
   4885 - (float)_footerHeight
   4886 {
   4887     return CallUIDelegateReturningFloat(self, @selector(webViewFooterHeight:));
   4888 }
   4889 
   4890 - (void)_drawHeaderInRect:(NSRect)rect
   4891 {
   4892 #ifdef DEBUG_HEADER_AND_FOOTER
   4893     NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
   4894     [currentContext saveGraphicsState];
   4895     [[NSColor yellowColor] set];
   4896     NSRectFill(rect);
   4897     [currentContext restoreGraphicsState];
   4898 #endif
   4899 
   4900     SEL selector = @selector(webView:drawHeaderInRect:);
   4901     if (![_private->UIDelegate respondsToSelector:selector])
   4902         return;
   4903 
   4904     NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
   4905     [currentContext saveGraphicsState];
   4906 
   4907     NSRectClip(rect);
   4908     CallUIDelegate(self, selector, rect);
   4909 
   4910     [currentContext restoreGraphicsState];
   4911 }
   4912 
   4913 - (void)_drawFooterInRect:(NSRect)rect
   4914 {
   4915 #ifdef DEBUG_HEADER_AND_FOOTER
   4916     NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
   4917     [currentContext saveGraphicsState];
   4918     [[NSColor cyanColor] set];
   4919     NSRectFill(rect);
   4920     [currentContext restoreGraphicsState];
   4921 #endif
   4922 
   4923     SEL selector = @selector(webView:drawFooterInRect:);
   4924     if (![_private->UIDelegate respondsToSelector:selector])
   4925         return;
   4926 
   4927     NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
   4928     [currentContext saveGraphicsState];
   4929 
   4930     NSRectClip(rect);
   4931     CallUIDelegate(self, selector, rect);
   4932 
   4933     [currentContext restoreGraphicsState];
   4934 }
   4935 
   4936 - (void)_adjustPrintingMarginsForHeaderAndFooter
   4937 {
   4938     NSPrintOperation *op = [NSPrintOperation currentOperation];
   4939     NSPrintInfo *info = [op printInfo];
   4940     NSMutableDictionary *infoDictionary = [info dictionary];
   4941 
   4942     // We need to modify the top and bottom margins in the NSPrintInfo to account for the space needed by the
   4943     // header and footer. Because this method can be called more than once on the same NSPrintInfo (see 5038087),
   4944     // we stash away the unmodified top and bottom margins the first time this method is called, and we read from
   4945     // those stashed-away values on subsequent calls.
   4946     float originalTopMargin;
   4947     float originalBottomMargin;
   4948     NSNumber *originalTopMarginNumber = [infoDictionary objectForKey:WebKitOriginalTopPrintingMarginKey];
   4949     if (!originalTopMarginNumber) {
   4950         ASSERT(![infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey]);
   4951         originalTopMargin = [info topMargin];
   4952         originalBottomMargin = [info bottomMargin];
   4953         [infoDictionary setObject:[NSNumber numberWithFloat:originalTopMargin] forKey:WebKitOriginalTopPrintingMarginKey];
   4954         [infoDictionary setObject:[NSNumber numberWithFloat:originalBottomMargin] forKey:WebKitOriginalBottomPrintingMarginKey];
   4955     } else {
   4956         ASSERT([originalTopMarginNumber isKindOfClass:[NSNumber class]]);
   4957         ASSERT([[infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey] isKindOfClass:[NSNumber class]]);
   4958         originalTopMargin = [originalTopMarginNumber floatValue];
   4959         originalBottomMargin = [[infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey] floatValue];
   4960     }
   4961 
   4962     float scale = [op _web_pageSetupScaleFactor];
   4963     [info setTopMargin:originalTopMargin + [self _headerHeight] * scale];
   4964     [info setBottomMargin:originalBottomMargin + [self _footerHeight] * scale];
   4965 }
   4966 
   4967 - (void)_drawHeaderAndFooter
   4968 {
   4969     // The header and footer rect height scales with the page, but the width is always
   4970     // all the way across the printed page (inset by printing margins).
   4971     NSPrintOperation *op = [NSPrintOperation currentOperation];
   4972     float scale = [op _web_pageSetupScaleFactor];
   4973     NSPrintInfo *printInfo = [op printInfo];
   4974     NSSize paperSize = [printInfo paperSize];
   4975     float headerFooterLeft = [printInfo leftMargin]/scale;
   4976     float headerFooterWidth = (paperSize.width - ([printInfo leftMargin] + [printInfo rightMargin]))/scale;
   4977     NSRect footerRect = NSMakeRect(headerFooterLeft, [printInfo bottomMargin]/scale - [self _footerHeight] ,
   4978                                    headerFooterWidth, [self _footerHeight]);
   4979     NSRect headerRect = NSMakeRect(headerFooterLeft, (paperSize.height - [printInfo topMargin])/scale,
   4980                                    headerFooterWidth, [self _headerHeight]);
   4981 
   4982     [self _drawHeaderInRect:headerRect];
   4983     [self _drawFooterInRect:footerRect];
   4984 }
   4985 @end
   4986 
   4987 @implementation WebView (WebDebugBinding)
   4988 
   4989 - (void)addObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context
   4990 {
   4991     LOG (Bindings, "addObserver:%p forKeyPath:%@ options:%x context:%p", anObserver, keyPath, options, context);
   4992     [super addObserver:anObserver forKeyPath:keyPath options:options context:context];
   4993 }
   4994 
   4995 - (void)removeObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath
   4996 {
   4997     LOG (Bindings, "removeObserver:%p forKeyPath:%@", anObserver, keyPath);
   4998     [super removeObserver:anObserver forKeyPath:keyPath];
   4999 }
   5000 
   5001 @end
   5002 
   5003 //==========================================================================================
   5004 // Editing
   5005 
   5006 @implementation WebView (WebViewCSS)
   5007 
   5008 - (DOMCSSStyleDeclaration *)computedStyleForElement:(DOMElement *)element pseudoElement:(NSString *)pseudoElement
   5009 {
   5010     // FIXME: is this the best level for this conversion?
   5011     if (pseudoElement == nil)
   5012         pseudoElement = @"";
   5013 
   5014     return [[element ownerDocument] getComputedStyle:element pseudoElement:pseudoElement];
   5015 }
   5016 
   5017 @end
   5018 
   5019 @implementation WebView (WebViewEditing)
   5020 
   5021 - (DOMRange *)editableDOMRangeForPoint:(NSPoint)point
   5022 {
   5023     Page* page = core(self);
   5024     if (!page)
   5025         return nil;
   5026     return kit(page->mainFrame()->editor()->rangeForPoint(IntPoint([self convertPoint:point toView:nil])).get());
   5027 }
   5028 
   5029 - (BOOL)_shouldChangeSelectedDOMRange:(DOMRange *)currentRange toDOMRange:(DOMRange *)proposedRange affinity:(NSSelectionAffinity)selectionAffinity stillSelecting:(BOOL)flag
   5030 {
   5031     // 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
   5032     if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_APERTURE_QUIRK) && [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.Aperture"])
   5033         return YES;
   5034     return [[self _editingDelegateForwarder] webView:self shouldChangeSelectedDOMRange:currentRange toDOMRange:proposedRange affinity:selectionAffinity stillSelecting:flag];
   5035 }
   5036 
   5037 - (BOOL)maintainsInactiveSelection
   5038 {
   5039     return NO;
   5040 }
   5041 
   5042 - (void)setSelectedDOMRange:(DOMRange *)range affinity:(NSSelectionAffinity)selectionAffinity
   5043 {
   5044     Frame* coreFrame = core([self _selectedOrMainFrame]);
   5045     if (!coreFrame)
   5046         return;
   5047 
   5048     if (range == nil)
   5049         coreFrame->selection()->clear();
   5050     else {
   5051         // Derive the frame to use from the range passed in.
   5052         // Using _selectedOrMainFrame could give us a different document than
   5053         // the one the range uses.
   5054         coreFrame = core([range startContainer])->document()->frame();
   5055         if (!coreFrame)
   5056             return;
   5057 
   5058         coreFrame->selection()->setSelectedRange(core(range), core(selectionAffinity), true);
   5059     }
   5060 }
   5061 
   5062 - (DOMRange *)selectedDOMRange
   5063 {
   5064     Frame* coreFrame = core([self _selectedOrMainFrame]);
   5065     if (!coreFrame)
   5066         return nil;
   5067     return kit(coreFrame->selection()->toNormalizedRange().get());
   5068 }
   5069 
   5070 - (NSSelectionAffinity)selectionAffinity
   5071 {
   5072     Frame* coreFrame = core([self _selectedOrMainFrame]);
   5073     if (!coreFrame)
   5074         return NSSelectionAffinityDownstream;
   5075     return kit(coreFrame->selection()->affinity());
   5076 }
   5077 
   5078 - (void)setEditable:(BOOL)flag
   5079 {
   5080     if ([self isEditable] != flag && _private->page) {
   5081         _private->page->setEditable(flag);
   5082         if (!_private->tabKeyCyclesThroughElementsChanged)
   5083             _private->page->setTabKeyCyclesThroughElements(!flag);
   5084         Frame* mainFrame = [self _mainCoreFrame];
   5085         if (mainFrame) {
   5086             if (flag) {
   5087                 mainFrame->editor()->applyEditingStyleToBodyElement();
   5088                 // If the WebView is made editable and the selection is empty, set it to something.
   5089                 if (![self selectedDOMRange])
   5090                     mainFrame->selection()->setSelectionFromNone();
   5091             }
   5092         }
   5093     }
   5094 }
   5095 
   5096 - (BOOL)isEditable
   5097 {
   5098     return _private->page && _private->page->isEditable();
   5099 }
   5100 
   5101 - (void)setTypingStyle:(DOMCSSStyleDeclaration *)style
   5102 {
   5103     // We don't know enough at thls level to pass in a relevant WebUndoAction; we'd have to
   5104     // change the API to allow this.
   5105     [[self _selectedOrMainFrame] _setTypingStyle:style withUndoAction:EditActionUnspecified];
   5106 }
   5107 
   5108 - (DOMCSSStyleDeclaration *)typingStyle
   5109 {
   5110     return [[self _selectedOrMainFrame] _typingStyle];
   5111 }
   5112 
   5113 - (void)setSmartInsertDeleteEnabled:(BOOL)flag
   5114 {
   5115     if (_private->smartInsertDeleteEnabled != flag) {
   5116         _private->smartInsertDeleteEnabled = flag;
   5117         [[NSUserDefaults standardUserDefaults] setBool:_private->smartInsertDeleteEnabled forKey:WebSmartInsertDeleteEnabled];
   5118     }
   5119     if (flag)
   5120         [self setSelectTrailingWhitespaceEnabled:false];
   5121 }
   5122 
   5123 - (BOOL)smartInsertDeleteEnabled
   5124 {
   5125     return _private->smartInsertDeleteEnabled;
   5126 }
   5127 
   5128 - (void)setContinuousSpellCheckingEnabled:(BOOL)flag
   5129 {
   5130     if (continuousSpellCheckingEnabled != flag) {
   5131         continuousSpellCheckingEnabled = flag;
   5132         [[NSUserDefaults standardUserDefaults] setBool:continuousSpellCheckingEnabled forKey:WebContinuousSpellCheckingEnabled];
   5133     }
   5134 
   5135     if ([self isContinuousSpellCheckingEnabled]) {
   5136         [[self class] _preflightSpellChecker];
   5137     } else {
   5138         [[self mainFrame] _unmarkAllMisspellings];
   5139     }
   5140 }
   5141 
   5142 - (BOOL)isContinuousSpellCheckingEnabled
   5143 {
   5144     return (continuousSpellCheckingEnabled && [self _continuousCheckingAllowed]);
   5145 }
   5146 
   5147 - (NSInteger)spellCheckerDocumentTag
   5148 {
   5149     if (!_private->hasSpellCheckerDocumentTag) {
   5150         _private->spellCheckerDocumentTag = [NSSpellChecker uniqueSpellDocumentTag];
   5151         _private->hasSpellCheckerDocumentTag = YES;
   5152     }
   5153     return _private->spellCheckerDocumentTag;
   5154 }
   5155 
   5156 - (NSUndoManager *)undoManager
   5157 {
   5158     if (!_private->allowsUndo)
   5159         return nil;
   5160 
   5161     NSUndoManager *undoManager = [[self _editingDelegateForwarder] undoManagerForWebView:self];
   5162     if (undoManager)
   5163         return undoManager;
   5164 
   5165     return [super undoManager];
   5166 }
   5167 
   5168 - (void)registerForEditingDelegateNotification:(NSString *)name selector:(SEL)selector
   5169 {
   5170     NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
   5171     if ([_private->editingDelegate respondsToSelector:selector])
   5172         [defaultCenter addObserver:_private->editingDelegate selector:selector name:name object:self];
   5173 }
   5174 
   5175 - (void)setEditingDelegate:(id)delegate
   5176 {
   5177     if (_private->editingDelegate == delegate)
   5178         return;
   5179 
   5180     NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
   5181 
   5182     // remove notifications from current delegate
   5183     [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidBeginEditingNotification object:self];
   5184     [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidChangeNotification object:self];
   5185     [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidEndEditingNotification object:self];
   5186     [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidChangeTypingStyleNotification object:self];
   5187     [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidChangeSelectionNotification object:self];
   5188 
   5189     _private->editingDelegate = delegate;
   5190     [_private->editingDelegateForwarder release];
   5191     _private->editingDelegateForwarder = nil;
   5192 
   5193     // add notifications for new delegate
   5194     [self registerForEditingDelegateNotification:WebViewDidBeginEditingNotification selector:@selector(webViewDidBeginEditing:)];
   5195     [self registerForEditingDelegateNotification:WebViewDidChangeNotification selector:@selector(webViewDidChange:)];
   5196     [self registerForEditingDelegateNotification:WebViewDidEndEditingNotification selector:@selector(webViewDidEndEditing:)];
   5197     [self registerForEditingDelegateNotification:WebViewDidChangeTypingStyleNotification selector:@selector(webViewDidChangeTypingStyle:)];
   5198     [self registerForEditingDelegateNotification:WebViewDidChangeSelectionNotification selector:@selector(webViewDidChangeSelection:)];
   5199 }
   5200 
   5201 - (id)editingDelegate
   5202 {
   5203     return _private->editingDelegate;
   5204 }
   5205 
   5206 - (DOMCSSStyleDeclaration *)styleDeclarationWithText:(NSString *)text
   5207 {
   5208     // FIXME: Should this really be attached to the document with the current selection?
   5209     DOMCSSStyleDeclaration *decl = [[[self _selectedOrMainFrame] DOMDocument] createCSSStyleDeclaration];
   5210     [decl setCssText:text];
   5211     return decl;
   5212 }
   5213 
   5214 @end
   5215 
   5216 @implementation WebView (WebViewGrammarChecking)
   5217 
   5218 // FIXME: This method should be merged into WebViewEditing when we're not in API freeze
   5219 - (BOOL)isGrammarCheckingEnabled
   5220 {
   5221 #ifdef BUILDING_ON_TIGER
   5222     return NO;
   5223 #else
   5224     return grammarCheckingEnabled;
   5225 #endif
   5226 }
   5227 
   5228 #ifndef BUILDING_ON_TIGER
   5229 // FIXME: This method should be merged into WebViewEditing when we're not in API freeze
   5230 - (void)setGrammarCheckingEnabled:(BOOL)flag
   5231 {
   5232     if (grammarCheckingEnabled == flag)
   5233         return;
   5234 
   5235     grammarCheckingEnabled = flag;
   5236     [[NSUserDefaults standardUserDefaults] setBool:grammarCheckingEnabled forKey:WebGrammarCheckingEnabled];
   5237 
   5238 #ifndef BUILDING_ON_LEOPARD
   5239     [[NSSpellChecker sharedSpellChecker] updatePanels];
   5240 #else
   5241     NSSpellChecker *spellChecker = [NSSpellChecker sharedSpellChecker];
   5242     if ([spellChecker respondsToSelector:@selector(_updateGrammar)])
   5243         [spellChecker performSelector:@selector(_updateGrammar)];
   5244 #endif
   5245 
   5246     // We call _preflightSpellChecker when turning continuous spell checking on, but we don't need to do that here
   5247     // because grammar checking only occurs on code paths that already preflight spell checking appropriately.
   5248 
   5249     if (![self isGrammarCheckingEnabled])
   5250         [[self mainFrame] _unmarkAllBadGrammar];
   5251 }
   5252 
   5253 // FIXME: This method should be merged into WebIBActions when we're not in API freeze
   5254 - (void)toggleGrammarChecking:(id)sender
   5255 {
   5256     [self setGrammarCheckingEnabled:![self isGrammarCheckingEnabled]];
   5257 }
   5258 #endif
   5259 
   5260 @end
   5261 
   5262 @implementation WebView (WebViewTextChecking)
   5263 
   5264 - (BOOL)isAutomaticQuoteSubstitutionEnabled
   5265 {
   5266 #if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
   5267     return NO;
   5268 #else
   5269     return automaticQuoteSubstitutionEnabled;
   5270 #endif
   5271 }
   5272 
   5273 - (BOOL)isAutomaticLinkDetectionEnabled
   5274 {
   5275 #if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
   5276     return NO;
   5277 #else
   5278     return automaticLinkDetectionEnabled;
   5279 #endif
   5280 }
   5281 
   5282 - (BOOL)isAutomaticDashSubstitutionEnabled
   5283 {
   5284 #if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
   5285     return NO;
   5286 #else
   5287     return automaticDashSubstitutionEnabled;
   5288 #endif
   5289 }
   5290 
   5291 - (BOOL)isAutomaticTextReplacementEnabled
   5292 {
   5293 #if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
   5294     return NO;
   5295 #else
   5296     return automaticTextReplacementEnabled;
   5297 #endif
   5298 }
   5299 
   5300 - (BOOL)isAutomaticSpellingCorrectionEnabled
   5301 {
   5302 #if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
   5303     return NO;
   5304 #else
   5305     return automaticSpellingCorrectionEnabled;
   5306 #endif
   5307 }
   5308 
   5309 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
   5310 
   5311 - (void)setAutomaticQuoteSubstitutionEnabled:(BOOL)flag
   5312 {
   5313     if (automaticQuoteSubstitutionEnabled == flag)
   5314         return;
   5315     automaticQuoteSubstitutionEnabled = flag;
   5316     [[NSUserDefaults standardUserDefaults] setBool:automaticQuoteSubstitutionEnabled forKey:WebAutomaticQuoteSubstitutionEnabled];
   5317     [[NSSpellChecker sharedSpellChecker] updatePanels];
   5318 }
   5319 
   5320 - (void)toggleAutomaticQuoteSubstitution:(id)sender
   5321 {
   5322     [self setAutomaticQuoteSubstitutionEnabled:![self isAutomaticQuoteSubstitutionEnabled]];
   5323 }
   5324 
   5325 - (void)setAutomaticLinkDetectionEnabled:(BOOL)flag
   5326 {
   5327     if (automaticLinkDetectionEnabled == flag)
   5328         return;
   5329     automaticLinkDetectionEnabled = flag;
   5330     [[NSUserDefaults standardUserDefaults] setBool:automaticLinkDetectionEnabled forKey:WebAutomaticLinkDetectionEnabled];
   5331     [[NSSpellChecker sharedSpellChecker] updatePanels];
   5332 }
   5333 
   5334 - (void)toggleAutomaticLinkDetection:(id)sender
   5335 {
   5336     [self setAutomaticLinkDetectionEnabled:![self isAutomaticLinkDetectionEnabled]];
   5337 }
   5338 
   5339 - (void)setAutomaticDashSubstitutionEnabled:(BOOL)flag
   5340 {
   5341     if (automaticDashSubstitutionEnabled == flag)
   5342         return;
   5343     automaticDashSubstitutionEnabled = flag;
   5344     [[NSUserDefaults standardUserDefaults] setBool:automaticDashSubstitutionEnabled forKey:WebAutomaticDashSubstitutionEnabled];
   5345     [[NSSpellChecker sharedSpellChecker] updatePanels];
   5346 }
   5347 
   5348 - (void)toggleAutomaticDashSubstitution:(id)sender
   5349 {
   5350     [self setAutomaticDashSubstitutionEnabled:![self isAutomaticDashSubstitutionEnabled]];
   5351 }
   5352 
   5353 - (void)setAutomaticTextReplacementEnabled:(BOOL)flag
   5354 {
   5355     if (automaticTextReplacementEnabled == flag)
   5356         return;
   5357     automaticTextReplacementEnabled = flag;
   5358     [[NSUserDefaults standardUserDefaults] setBool:automaticTextReplacementEnabled forKey:WebAutomaticTextReplacementEnabled];
   5359     [[NSSpellChecker sharedSpellChecker] updatePanels];
   5360 }
   5361 
   5362 - (void)toggleAutomaticTextReplacement:(id)sender
   5363 {
   5364     [self setAutomaticTextReplacementEnabled:![self isAutomaticTextReplacementEnabled]];
   5365 }
   5366 
   5367 - (void)setAutomaticSpellingCorrectionEnabled:(BOOL)flag
   5368 {
   5369     if (automaticSpellingCorrectionEnabled == flag)
   5370         return;
   5371     automaticSpellingCorrectionEnabled = flag;
   5372     [[NSUserDefaults standardUserDefaults] setBool:automaticSpellingCorrectionEnabled forKey:WebAutomaticSpellingCorrectionEnabled];
   5373     [[NSSpellChecker sharedSpellChecker] updatePanels];
   5374 }
   5375 
   5376 - (void)toggleAutomaticSpellingCorrection:(id)sender
   5377 {
   5378     [self setAutomaticSpellingCorrectionEnabled:![self isAutomaticSpellingCorrectionEnabled]];
   5379 }
   5380 
   5381 #endif
   5382 
   5383 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
   5384 - (void)handleCorrectionPanelResult:(NSString*)result
   5385 {
   5386     WebFrame *webFrame = [self _selectedOrMainFrame];
   5387     Frame* coreFrame = core(webFrame);
   5388     if (coreFrame)
   5389         coreFrame->editor()->handleCorrectionPanelResult(result);
   5390 }
   5391 #endif
   5392 
   5393 @end
   5394 
   5395 @implementation WebView (WebViewUndoableEditing)
   5396 
   5397 - (void)replaceSelectionWithNode:(DOMNode *)node
   5398 {
   5399     [[self _selectedOrMainFrame] _replaceSelectionWithNode:node selectReplacement:YES smartReplace:NO matchStyle:NO];
   5400 }
   5401 
   5402 - (void)replaceSelectionWithText:(NSString *)text
   5403 {
   5404     [[self _selectedOrMainFrame] _replaceSelectionWithText:text selectReplacement:YES smartReplace:NO];
   5405 }
   5406 
   5407 - (void)replaceSelectionWithMarkupString:(NSString *)markupString
   5408 {
   5409     [[self _selectedOrMainFrame] _replaceSelectionWithMarkupString:markupString baseURLString:nil selectReplacement:YES smartReplace:NO];
   5410 }
   5411 
   5412 - (void)replaceSelectionWithArchive:(WebArchive *)archive
   5413 {
   5414     [[[self _selectedOrMainFrame] _dataSource] _replaceSelectionWithArchive:archive selectReplacement:YES];
   5415 }
   5416 
   5417 - (void)deleteSelection
   5418 {
   5419     WebFrame *webFrame = [self _selectedOrMainFrame];
   5420     Frame* coreFrame = core(webFrame);
   5421     if (coreFrame)
   5422         coreFrame->editor()->deleteSelectionWithSmartDelete([(WebHTMLView *)[[webFrame frameView] documentView] _canSmartCopyOrDelete]);
   5423 }
   5424 
   5425 - (void)applyStyle:(DOMCSSStyleDeclaration *)style
   5426 {
   5427     // We don't know enough at thls level to pass in a relevant WebUndoAction; we'd have to
   5428     // change the API to allow this.
   5429     WebFrame *webFrame = [self _selectedOrMainFrame];
   5430     Frame* coreFrame = core(webFrame);
   5431     if (coreFrame)
   5432         coreFrame->editor()->applyStyle(core(style));
   5433 }
   5434 
   5435 @end
   5436 
   5437 @implementation WebView (WebViewEditingActions)
   5438 
   5439 - (void)_performResponderOperation:(SEL)selector with:(id)parameter
   5440 {
   5441     static BOOL reentered = NO;
   5442     if (reentered) {
   5443         [[self nextResponder] tryToPerform:selector with:parameter];
   5444         return;
   5445     }
   5446 
   5447     // There are two possibilities here.
   5448     //
   5449     // One is that WebView has been called in its role as part of the responder chain.
   5450     // In that case, it's fine to call the first responder and end up calling down the
   5451     // responder chain again. Later we will return here with reentered = YES and continue
   5452     // past the WebView.
   5453     //
   5454     // The other is that we are being called directly, in which case we want to pass the
   5455     // selector down to the view inside us that can handle it, and continue down the
   5456     // responder chain as usual.
   5457 
   5458     // Pass this selector down to the first responder.
   5459     NSResponder *responder = [self _responderForResponderOperations];
   5460     reentered = YES;
   5461     [responder tryToPerform:selector with:parameter];
   5462     reentered = NO;
   5463 }
   5464 
   5465 #define FORWARD(name) \
   5466     - (void)name:(id)sender { [self _performResponderOperation:_cmd with:sender]; }
   5467 
   5468 FOR_EACH_RESPONDER_SELECTOR(FORWARD)
   5469 
   5470 - (void)insertText:(NSString *)text
   5471 {
   5472     [self _performResponderOperation:_cmd with:text];
   5473 }
   5474 
   5475 @end
   5476 
   5477 @implementation WebView (WebViewEditingInMail)
   5478 
   5479 - (void)_insertNewlineInQuotedContent
   5480 {
   5481     [[self _selectedOrMainFrame] _insertParagraphSeparatorInQuotedContent];
   5482 }
   5483 
   5484 - (void)_replaceSelectionWithNode:(DOMNode *)node matchStyle:(BOOL)matchStyle
   5485 {
   5486     [[self _selectedOrMainFrame] _replaceSelectionWithNode:node selectReplacement:YES smartReplace:NO matchStyle:matchStyle];
   5487 }
   5488 
   5489 - (BOOL)_selectionIsCaret
   5490 {
   5491     Frame* coreFrame = core([self _selectedOrMainFrame]);
   5492     if (!coreFrame)
   5493         return NO;
   5494     return coreFrame->selection()->isCaret();
   5495 }
   5496 
   5497 - (BOOL)_selectionIsAll
   5498 {
   5499     Frame* coreFrame = core([self _selectedOrMainFrame]);
   5500     if (!coreFrame)
   5501         return NO;
   5502     return coreFrame->selection()->isAll(CanCrossEditingBoundary);
   5503 }
   5504 
   5505 @end
   5506 
   5507 static WebFrameView *containingFrameView(NSView *view)
   5508 {
   5509     while (view && ![view isKindOfClass:[WebFrameView class]])
   5510         view = [view superview];
   5511     return (WebFrameView *)view;
   5512 }
   5513 
   5514 @implementation WebView (WebFileInternal)
   5515 
   5516 static inline uint64_t roundUpToPowerOf2(uint64_t num)
   5517 {
   5518     return powf(2.0, ceilf(log2f(num)));
   5519 }
   5520 
   5521 + (void)_setCacheModel:(WebCacheModel)cacheModel
   5522 {
   5523     if (s_didSetCacheModel && cacheModel == s_cacheModel)
   5524         return;
   5525 
   5526     NSString *nsurlCacheDirectory = (NSString *)WebCFAutorelease(WKCopyFoundationCacheDirectory());
   5527     if (!nsurlCacheDirectory)
   5528         nsurlCacheDirectory = NSHomeDirectory();
   5529 
   5530     static uint64_t memSize = roundUpToPowerOf2(WebMemorySize() / 1024 / 1024);
   5531     unsigned long long diskFreeSize = WebVolumeFreeSize(nsurlCacheDirectory) / 1024 / 1000;
   5532     NSURLCache *nsurlCache = [NSURLCache sharedURLCache];
   5533 
   5534     unsigned cacheTotalCapacity = 0;
   5535     unsigned cacheMinDeadCapacity = 0;
   5536     unsigned cacheMaxDeadCapacity = 0;
   5537     double deadDecodedDataDeletionInterval = 0;
   5538 
   5539     unsigned pageCacheCapacity = 0;
   5540 
   5541     NSUInteger nsurlCacheMemoryCapacity = 0;
   5542     NSUInteger nsurlCacheDiskCapacity = 0;
   5543 
   5544     switch (cacheModel) {
   5545     case WebCacheModelDocumentViewer: {
   5546         // Page cache capacity (in pages)
   5547         pageCacheCapacity = 0;
   5548 
   5549         // Object cache capacities (in bytes)
   5550         if (memSize >= 4096)
   5551             cacheTotalCapacity = 128 * 1024 * 1024;
   5552         else if (memSize >= 2048)
   5553             cacheTotalCapacity = 96 * 1024 * 1024;
   5554         else if (memSize >= 1024)
   5555             cacheTotalCapacity = 32 * 1024 * 1024;
   5556         else if (memSize >= 512)
   5557             cacheTotalCapacity = 16 * 1024 * 1024;
   5558 
   5559         cacheMinDeadCapacity = 0;
   5560         cacheMaxDeadCapacity = 0;
   5561 
   5562         // Foundation memory cache capacity (in bytes)
   5563         nsurlCacheMemoryCapacity = 0;
   5564 
   5565         // Foundation disk cache capacity (in bytes)
   5566         nsurlCacheDiskCapacity = [nsurlCache diskCapacity];
   5567 
   5568         break;
   5569     }
   5570     case WebCacheModelDocumentBrowser: {
   5571         // Page cache capacity (in pages)
   5572         if (memSize >= 1024)
   5573             pageCacheCapacity = 3;
   5574         else if (memSize >= 512)
   5575             pageCacheCapacity = 2;
   5576         else if (memSize >= 256)
   5577             pageCacheCapacity = 1;
   5578         else
   5579             pageCacheCapacity = 0;
   5580 
   5581         // Object cache capacities (in bytes)
   5582         if (memSize >= 4096)
   5583             cacheTotalCapacity = 128 * 1024 * 1024;
   5584         else if (memSize >= 2048)
   5585             cacheTotalCapacity = 96 * 1024 * 1024;
   5586         else if (memSize >= 1024)
   5587             cacheTotalCapacity = 32 * 1024 * 1024;
   5588         else if (memSize >= 512)
   5589             cacheTotalCapacity = 16 * 1024 * 1024;
   5590 
   5591         cacheMinDeadCapacity = cacheTotalCapacity / 8;
   5592         cacheMaxDeadCapacity = cacheTotalCapacity / 4;
   5593 
   5594         // Foundation memory cache capacity (in bytes)
   5595         if (memSize >= 2048)
   5596             nsurlCacheMemoryCapacity = 4 * 1024 * 1024;
   5597         else if (memSize >= 1024)
   5598             nsurlCacheMemoryCapacity = 2 * 1024 * 1024;
   5599         else if (memSize >= 512)
   5600             nsurlCacheMemoryCapacity = 1 * 1024 * 1024;
   5601         else
   5602             nsurlCacheMemoryCapacity =      512 * 1024;
   5603 
   5604         // Foundation disk cache capacity (in bytes)
   5605         if (diskFreeSize >= 16384)
   5606             nsurlCacheDiskCapacity = 50 * 1024 * 1024;
   5607         else if (diskFreeSize >= 8192)
   5608             nsurlCacheDiskCapacity = 40 * 1024 * 1024;
   5609         else if (diskFreeSize >= 4096)
   5610             nsurlCacheDiskCapacity = 30 * 1024 * 1024;
   5611         else
   5612             nsurlCacheDiskCapacity = 20 * 1024 * 1024;
   5613 
   5614         break;
   5615     }
   5616     case WebCacheModelPrimaryWebBrowser: {
   5617         // Page cache capacity (in pages)
   5618         // (Research indicates that value / page drops substantially after 3 pages.)
   5619         if (memSize >= 2048)
   5620             pageCacheCapacity = 5;
   5621         else if (memSize >= 1024)
   5622             pageCacheCapacity = 4;
   5623         else if (memSize >= 512)
   5624             pageCacheCapacity = 3;
   5625         else if (memSize >= 256)
   5626             pageCacheCapacity = 2;
   5627         else
   5628             pageCacheCapacity = 1;
   5629 
   5630         // Object cache capacities (in bytes)
   5631         // (Testing indicates that value / MB depends heavily on content and
   5632         // browsing pattern. Even growth above 128MB can have substantial
   5633         // value / MB for some content / browsing patterns.)
   5634         if (memSize >= 4096)
   5635             cacheTotalCapacity = 192 * 1024 * 1024;
   5636         else if (memSize >= 2048)
   5637             cacheTotalCapacity = 128 * 1024 * 1024;
   5638         else if (memSize >= 1024)
   5639             cacheTotalCapacity = 64 * 1024 * 1024;
   5640         else if (memSize >= 512)
   5641             cacheTotalCapacity = 32 * 1024 * 1024;
   5642 
   5643         cacheMinDeadCapacity = cacheTotalCapacity / 4;
   5644         cacheMaxDeadCapacity = cacheTotalCapacity / 2;
   5645 
   5646         // This code is here to avoid a PLT regression. We can remove it if we
   5647         // can prove that the overall system gain would justify the regression.
   5648         cacheMaxDeadCapacity = max(24u, cacheMaxDeadCapacity);
   5649 
   5650         deadDecodedDataDeletionInterval = 60;
   5651 
   5652         // Foundation memory cache capacity (in bytes)
   5653         // (These values are small because WebCore does most caching itself.)
   5654         if (memSize >= 1024)
   5655             nsurlCacheMemoryCapacity = 4 * 1024 * 1024;
   5656         else if (memSize >= 512)
   5657             nsurlCacheMemoryCapacity = 2 * 1024 * 1024;
   5658         else if (memSize >= 256)
   5659             nsurlCacheMemoryCapacity = 1 * 1024 * 1024;
   5660         else
   5661             nsurlCacheMemoryCapacity =      512 * 1024;
   5662 
   5663         // Foundation disk cache capacity (in bytes)
   5664         if (diskFreeSize >= 16384)
   5665             nsurlCacheDiskCapacity = 175 * 1024 * 1024;
   5666         else if (diskFreeSize >= 8192)
   5667             nsurlCacheDiskCapacity = 150 * 1024 * 1024;
   5668         else if (diskFreeSize >= 4096)
   5669             nsurlCacheDiskCapacity = 125 * 1024 * 1024;
   5670         else if (diskFreeSize >= 2048)
   5671             nsurlCacheDiskCapacity = 100 * 1024 * 1024;
   5672         else if (diskFreeSize >= 1024)
   5673             nsurlCacheDiskCapacity = 75 * 1024 * 1024;
   5674         else
   5675             nsurlCacheDiskCapacity = 50 * 1024 * 1024;
   5676 
   5677         break;
   5678     }
   5679     default:
   5680         ASSERT_NOT_REACHED();
   5681     };
   5682 
   5683 #ifdef BUILDING_ON_TIGER
   5684     // Don't use a big Foundation disk cache on Tiger because, according to the
   5685     // PLT, the Foundation disk cache on Tiger is slower than the network.
   5686     nsurlCacheDiskCapacity = [nsurlCache diskCapacity];
   5687 #endif
   5688 
   5689     // Don't shrink a big disk cache, since that would cause churn.
   5690     nsurlCacheDiskCapacity = max(nsurlCacheDiskCapacity, [nsurlCache diskCapacity]);
   5691 
   5692     memoryCache()->setCapacities(cacheMinDeadCapacity, cacheMaxDeadCapacity, cacheTotalCapacity);
   5693     memoryCache()->setDeadDecodedDataDeletionInterval(deadDecodedDataDeletionInterval);
   5694     pageCache()->setCapacity(pageCacheCapacity);
   5695     [nsurlCache setMemoryCapacity:nsurlCacheMemoryCapacity];
   5696     [nsurlCache setDiskCapacity:nsurlCacheDiskCapacity];
   5697 
   5698     s_cacheModel = cacheModel;
   5699     s_didSetCacheModel = YES;
   5700 }
   5701 
   5702 + (WebCacheModel)_cacheModel
   5703 {
   5704     return s_cacheModel;
   5705 }
   5706 
   5707 + (WebCacheModel)_didSetCacheModel
   5708 {
   5709     return s_didSetCacheModel;
   5710 }
   5711 
   5712 + (WebCacheModel)_maxCacheModelInAnyInstance
   5713 {
   5714     WebCacheModel cacheModel = WebCacheModelDocumentViewer;
   5715     NSEnumerator *enumerator = [(NSMutableSet *)allWebViewsSet objectEnumerator];
   5716     while (WebPreferences *preferences = [[enumerator nextObject] preferences])
   5717         cacheModel = max(cacheModel, [preferences cacheModel]);
   5718     return cacheModel;
   5719 }
   5720 
   5721 + (void)_preferencesChangedNotification:(NSNotification *)notification
   5722 {
   5723     WebPreferences *preferences = (WebPreferences *)[notification object];
   5724     ASSERT([preferences isKindOfClass:[WebPreferences class]]);
   5725 
   5726     WebCacheModel cacheModel = [preferences cacheModel];
   5727     if (![self _didSetCacheModel] || cacheModel > [self _cacheModel])
   5728         [self _setCacheModel:cacheModel];
   5729     else if (cacheModel < [self _cacheModel])
   5730         [self _setCacheModel:max([[WebPreferences standardPreferences] cacheModel], [self _maxCacheModelInAnyInstance])];
   5731 }
   5732 
   5733 + (void)_preferencesRemovedNotification:(NSNotification *)notification
   5734 {
   5735     WebPreferences *preferences = (WebPreferences *)[notification object];
   5736     ASSERT([preferences isKindOfClass:[WebPreferences class]]);
   5737 
   5738     if ([preferences cacheModel] == [self _cacheModel])
   5739         [self _setCacheModel:max([[WebPreferences standardPreferences] cacheModel], [self _maxCacheModelInAnyInstance])];
   5740 }
   5741 
   5742 - (WebFrame *)_focusedFrame
   5743 {
   5744     NSResponder *resp = [[self window] firstResponder];
   5745     if (resp && [resp isKindOfClass:[NSView class]] && [(NSView *)resp isDescendantOf:[[self mainFrame] frameView]]) {
   5746         WebFrameView *frameView = containingFrameView((NSView *)resp);
   5747         ASSERT(frameView != nil);
   5748         return [frameView webFrame];
   5749     }
   5750 
   5751     return nil;
   5752 }
   5753 
   5754 - (BOOL)_isLoading
   5755 {
   5756     WebFrame *mainFrame = [self mainFrame];
   5757     return [[mainFrame _dataSource] isLoading]
   5758         || [[mainFrame provisionalDataSource] isLoading];
   5759 }
   5760 
   5761 - (WebFrameView *)_frameViewAtWindowPoint:(NSPoint)point
   5762 {
   5763     if (_private->closed)
   5764         return nil;
   5765     ASSERT(_private->usesDocumentViews);
   5766     NSView *view = [self hitTest:[[self superview] convertPoint:point fromView:nil]];
   5767     if (![view isDescendantOf:[[self mainFrame] frameView]])
   5768         return nil;
   5769     WebFrameView *frameView = containingFrameView(view);
   5770     ASSERT(frameView);
   5771     return frameView;
   5772 }
   5773 
   5774 + (void)_preflightSpellCheckerNow:(id)sender
   5775 {
   5776     [[NSSpellChecker sharedSpellChecker] _preflightChosenSpellServer];
   5777 }
   5778 
   5779 + (void)_preflightSpellChecker
   5780 {
   5781     // As AppKit does, we wish to delay tickling the shared spellchecker into existence on application launch.
   5782     if ([NSSpellChecker sharedSpellCheckerExists]) {
   5783         [self _preflightSpellCheckerNow:self];
   5784     } else {
   5785         [self performSelector:@selector(_preflightSpellCheckerNow:) withObject:self afterDelay:2.0];
   5786     }
   5787 }
   5788 
   5789 - (BOOL)_continuousCheckingAllowed
   5790 {
   5791     static BOOL allowContinuousSpellChecking = YES;
   5792     static BOOL readAllowContinuousSpellCheckingDefault = NO;
   5793     if (!readAllowContinuousSpellCheckingDefault) {
   5794         if ([[NSUserDefaults standardUserDefaults] objectForKey:@"NSAllowContinuousSpellChecking"]) {
   5795             allowContinuousSpellChecking = [[NSUserDefaults standardUserDefaults] boolForKey:@"NSAllowContinuousSpellChecking"];
   5796         }
   5797         readAllowContinuousSpellCheckingDefault = YES;
   5798     }
   5799     return allowContinuousSpellChecking;
   5800 }
   5801 
   5802 - (NSResponder *)_responderForResponderOperations
   5803 {
   5804     NSResponder *responder = [[self window] firstResponder];
   5805     WebFrameView *mainFrameView = [[self mainFrame] frameView];
   5806 
   5807     // If the current responder is outside of the webview, use our main frameView or its
   5808     // document view. We also do this for subviews of self that are siblings of the main
   5809     // frameView since clients might insert non-webview-related views there (see 4552713).
   5810     if (responder != self && ![mainFrameView _web_firstResponderIsSelfOrDescendantView]) {
   5811         responder = [mainFrameView documentView];
   5812         if (!responder)
   5813             responder = mainFrameView;
   5814     }
   5815     return responder;
   5816 }
   5817 
   5818 - (void)_openFrameInNewWindowFromMenu:(NSMenuItem *)sender
   5819 {
   5820     ASSERT_ARG(sender, [sender isKindOfClass:[NSMenuItem class]]);
   5821 
   5822     NSDictionary *element = [sender representedObject];
   5823     ASSERT([element isKindOfClass:[NSDictionary class]]);
   5824 
   5825     WebDataSource *dataSource = [(WebFrame *)[element objectForKey:WebElementFrameKey] dataSource];
   5826     NSURLRequest *request = [[dataSource request] copy];
   5827     ASSERT(request);
   5828 
   5829     [self _openNewWindowWithRequest:request];
   5830     [request release];
   5831 }
   5832 
   5833 - (void)_searchWithGoogleFromMenu:(id)sender
   5834 {
   5835     id documentView = [[[self selectedFrame] frameView] documentView];
   5836     if (![documentView conformsToProtocol:@protocol(WebDocumentText)]) {
   5837         return;
   5838     }
   5839 
   5840     NSString *selectedString = [(id <WebDocumentText>)documentView selectedString];
   5841     if ([selectedString length] == 0) {
   5842         return;
   5843     }
   5844 
   5845     NSPasteboard *pasteboard = [NSPasteboard pasteboardWithUniqueName];
   5846     [pasteboard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
   5847     NSMutableString *s = [selectedString mutableCopy];
   5848     const unichar nonBreakingSpaceCharacter = 0xA0;
   5849     NSString *nonBreakingSpaceString = [NSString stringWithCharacters:&nonBreakingSpaceCharacter length:1];
   5850     [s replaceOccurrencesOfString:nonBreakingSpaceString withString:@" " options:0 range:NSMakeRange(0, [s length])];
   5851     [pasteboard setString:s forType:NSStringPboardType];
   5852     [s release];
   5853 
   5854     // FIXME: seems fragile to use the service by name, but this is what AppKit does
   5855     NSPerformService(@"Search With Google", pasteboard);
   5856 }
   5857 
   5858 - (void)_searchWithSpotlightFromMenu:(id)sender
   5859 {
   5860     id documentView = [[[self selectedFrame] frameView] documentView];
   5861     if (![documentView conformsToProtocol:@protocol(WebDocumentText)])
   5862         return;
   5863 
   5864     NSString *selectedString = [(id <WebDocumentText>)documentView selectedString];
   5865     if (![selectedString length])
   5866         return;
   5867 
   5868 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
   5869     [[NSWorkspace sharedWorkspace] showSearchResultsForQueryString:selectedString];
   5870 #else
   5871     (void)HISearchWindowShow((CFStringRef)selectedString, kNilOptions);
   5872 #endif
   5873 }
   5874 
   5875 #if USE(ACCELERATED_COMPOSITING)
   5876 - (void)_clearLayerSyncLoopObserver
   5877 {
   5878     if (!_private->layerSyncRunLoopObserver)
   5879         return;
   5880 
   5881     CFRunLoopObserverInvalidate(_private->layerSyncRunLoopObserver);
   5882     CFRelease(_private->layerSyncRunLoopObserver);
   5883     _private->layerSyncRunLoopObserver = 0;
   5884 }
   5885 #endif
   5886 
   5887 #if ENABLE(GLIB_SUPPORT)
   5888 - (void)_clearGlibLoopObserver
   5889 {
   5890     if (!_private->glibRunLoopObserver)
   5891         return;
   5892 
   5893     CFRunLoopObserverInvalidate(_private->glibRunLoopObserver);
   5894     CFRelease(_private->glibRunLoopObserver);
   5895     _private->glibRunLoopObserver = 0;
   5896 }
   5897 #endif
   5898 @end
   5899 
   5900 @implementation WebView (WebViewInternal)
   5901 
   5902 + (BOOL)shouldIncludeInWebKitStatistics
   5903 {
   5904     return NO;
   5905 }
   5906 
   5907 - (BOOL)_becomingFirstResponderFromOutside
   5908 {
   5909     return _private->becomingFirstResponderFromOutside;
   5910 }
   5911 
   5912 #if ENABLE(ICONDATABASE)
   5913 - (void)_receivedIconChangedNotification:(NSNotification *)notification
   5914 {
   5915     // Get the URL for this notification
   5916     NSDictionary *userInfo = [notification userInfo];
   5917     ASSERT([userInfo isKindOfClass:[NSDictionary class]]);
   5918     NSString *urlString = [userInfo objectForKey:WebIconNotificationUserInfoURLKey];
   5919     ASSERT([urlString isKindOfClass:[NSString class]]);
   5920 
   5921     // If that URL matches the current main frame, dispatch the delegate call, which will also unregister
   5922     // us for this notification
   5923     if ([[self mainFrameURL] isEqualTo:urlString])
   5924         [self _dispatchDidReceiveIconFromWebFrame:[self mainFrame]];
   5925 }
   5926 
   5927 - (void)_registerForIconNotification:(BOOL)listen
   5928 {
   5929     if (listen)
   5930         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_receivedIconChangedNotification:) name:WebIconDatabaseDidAddIconNotification object:nil];
   5931     else
   5932         [[NSNotificationCenter defaultCenter] removeObserver:self name:WebIconDatabaseDidAddIconNotification object:nil];
   5933 }
   5934 
   5935 - (void)_dispatchDidReceiveIconFromWebFrame:(WebFrame *)webFrame
   5936 {
   5937     // FIXME: This willChangeValueForKey call is too late, because the icon has already changed by now.
   5938     [self _willChangeValueForKey:_WebMainFrameIconKey];
   5939 
   5940     // 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
   5941     // notification any longer
   5942     [self _registerForIconNotification:NO];
   5943 
   5944     WebFrameLoadDelegateImplementationCache* cache = &_private->frameLoadDelegateImplementations;
   5945     if (cache->didReceiveIconForFrameFunc) {
   5946         Image* image = iconDatabase().synchronousIconForPageURL(core(webFrame)->document()->url().string(), IntSize(16, 16));
   5947         if (NSImage *icon = webGetNSImage(image, NSMakeSize(16, 16)))
   5948             CallFrameLoadDelegate(cache->didReceiveIconForFrameFunc, self, @selector(webView:didReceiveIcon:forFrame:), icon, webFrame);
   5949     }
   5950 
   5951     [self _didChangeValueForKey:_WebMainFrameIconKey];
   5952 }
   5953 #endif // ENABLE(ICONDATABASE)
   5954 
   5955 - (void)_addObject:(id)object forIdentifier:(unsigned long)identifier
   5956 {
   5957     ASSERT(!_private->identifierMap.contains(identifier));
   5958 
   5959     // If the identifier map is initially empty it means we're starting a load
   5960     // of something. The semantic is that the web view should be around as long
   5961     // as something is loading. Because of that we retain the web view.
   5962     if (_private->identifierMap.isEmpty())
   5963         CFRetain(self);
   5964 
   5965     _private->identifierMap.set(identifier, object);
   5966 }
   5967 
   5968 - (id)_objectForIdentifier:(unsigned long)identifier
   5969 {
   5970     return _private->identifierMap.get(identifier).get();
   5971 }
   5972 
   5973 - (void)_removeObjectForIdentifier:(unsigned long)identifier
   5974 {
   5975     ASSERT(_private->identifierMap.contains(identifier));
   5976     _private->identifierMap.remove(identifier);
   5977 
   5978     // If the identifier map is now empty it means we're no longer loading anything
   5979     // and we should release the web view.
   5980     if (_private->identifierMap.isEmpty())
   5981         CFRelease(self);
   5982 }
   5983 
   5984 - (void)_retrieveKeyboardUIModeFromPreferences:(NSNotification *)notification
   5985 {
   5986     CFPreferencesAppSynchronize(UniversalAccessDomain);
   5987 
   5988     Boolean keyExistsAndHasValidFormat;
   5989     int mode = CFPreferencesGetAppIntegerValue(AppleKeyboardUIMode, UniversalAccessDomain, &keyExistsAndHasValidFormat);
   5990 
   5991     // The keyboard access mode is reported by two bits:
   5992     // Bit 0 is set if feature is on
   5993     // Bit 1 is set if full keyboard access works for any control, not just text boxes and lists
   5994     _private->_keyboardUIMode = (mode & 0x2) ? KeyboardAccessFull : KeyboardAccessDefault;
   5995 
   5996     // check for tabbing to links
   5997     if ([_private->preferences tabsToLinks])
   5998         _private->_keyboardUIMode = (KeyboardUIMode)(_private->_keyboardUIMode | KeyboardAccessTabsToLinks);
   5999 }
   6000 
   6001 - (KeyboardUIMode)_keyboardUIMode
   6002 {
   6003     if (!_private->_keyboardUIModeAccessed) {
   6004         _private->_keyboardUIModeAccessed = YES;
   6005 
   6006         [self _retrieveKeyboardUIModeFromPreferences:nil];
   6007 
   6008         [[NSDistributedNotificationCenter defaultCenter]
   6009             addObserver:self selector:@selector(_retrieveKeyboardUIModeFromPreferences:)
   6010             name:KeyboardUIModeDidChangeNotification object:nil];
   6011 
   6012         [[NSNotificationCenter defaultCenter]
   6013             addObserver:self selector:@selector(_retrieveKeyboardUIModeFromPreferences:)
   6014             name:WebPreferencesChangedInternalNotification object:nil];
   6015     }
   6016     return _private->_keyboardUIMode;
   6017 }
   6018 
   6019 - (void)_setInsertionPasteboard:(NSPasteboard *)pasteboard
   6020 {
   6021     _private->insertionPasteboard = pasteboard;
   6022 }
   6023 
   6024 - (void)_selectionChanged
   6025 {
   6026     if (_private->usesDocumentViews) {
   6027         id documentView = [[[self _selectedOrMainFrame] frameView] documentView];
   6028         if ([documentView isKindOfClass:[WebHTMLView class]])
   6029             [documentView _selectionChanged];
   6030         return;
   6031     }
   6032 
   6033     // FIXME (Viewless): We'll need code here.
   6034 }
   6035 
   6036 - (Frame*)_mainCoreFrame
   6037 {
   6038     return (_private && _private->page) ? _private->page->mainFrame() : 0;
   6039 }
   6040 
   6041 - (WebFrame *)_selectedOrMainFrame
   6042 {
   6043     WebFrame *result = [self selectedFrame];
   6044     if (result == nil)
   6045         result = [self mainFrame];
   6046     return result;
   6047 }
   6048 
   6049 #if USE(ACCELERATED_COMPOSITING)
   6050 
   6051 - (BOOL)_needsOneShotDrawingSynchronization
   6052 {
   6053     return _private->needsOneShotDrawingSynchronization;
   6054 }
   6055 
   6056 - (void)_setNeedsOneShotDrawingSynchronization:(BOOL)needsSynchronization
   6057 {
   6058     _private->needsOneShotDrawingSynchronization = needsSynchronization;
   6059 }
   6060 
   6061 - (BOOL)_syncCompositingChanges
   6062 {
   6063     Frame* frame = [self _mainCoreFrame];
   6064     if (frame && frame->view())
   6065         return frame->view()->syncCompositingStateIncludingSubframes();
   6066 
   6067     return YES;
   6068 }
   6069 
   6070 /*
   6071     The order of events with compositing updates is this:
   6072 
   6073    Start of runloop                                        End of runloop
   6074         |                                                       |
   6075       --|-------------------------------------------------------|--
   6076            ^         ^                                        ^
   6077            |         |                                        |
   6078     NSWindow update, |                                     CA commit
   6079      NSView drawing  |
   6080         flush        |
   6081                 layerSyncRunLoopObserverCallBack
   6082 
   6083     To avoid flashing, we have to ensure that compositing changes (rendered via
   6084     the CoreAnimation rendering display link) appear on screen at the same time
   6085     as content painted into the window via the normal WebCore rendering path.
   6086 
   6087     CoreAnimation will commit any layer changes at the end of the runloop via
   6088     its "CA commit" observer. Those changes can then appear onscreen at any time
   6089     when the display link fires, which can result in unsynchronized rendering.
   6090 
   6091     To fix this, the GraphicsLayerCA code in WebCore does not change the CA
   6092     layer tree during style changes and layout; it stores up all changes and
   6093     commits them via syncCompositingState(). There are then two situations in
   6094     which we can call syncCompositingState():
   6095 
   6096     1. When painting. FrameView::paintContents() makes a call to syncCompositingState().
   6097 
   6098     2. When style changes/layout have made changes to the layer tree which do not
   6099        result in painting. In this case we need a run loop observer to do a
   6100        syncCompositingState() at an appropriate time. The observer will keep firing
   6101        until the time is right (essentially when there are no more pending layouts).
   6102 
   6103 */
   6104 
   6105 static void layerSyncRunLoopObserverCallBack(CFRunLoopObserverRef, CFRunLoopActivity, void* info)
   6106 {
   6107     WebView *webView = reinterpret_cast<WebView*>(info);
   6108     NSWindow *window = [webView window];
   6109 
   6110     // An NSWindow may not display in the next runloop cycle after dirtying due to delayed window display logic,
   6111     // in which case this observer can fire first. So if the window is due for a display, don't commit
   6112     // layer changes, otherwise they'll show on screen before the view drawing.
   6113     bool viewsNeedDisplay;
   6114 #ifndef __LP64__
   6115     if (window && [window _wrapsCarbonWindow])
   6116         viewsNeedDisplay = HIViewGetNeedsDisplay(HIViewGetRoot(static_cast<WindowRef>([window windowRef])));
   6117     else
   6118 #endif
   6119         viewsNeedDisplay = [window viewsNeedDisplay];
   6120 
   6121     if (viewsNeedDisplay)
   6122         return;
   6123 
   6124     if ([webView _syncCompositingChanges]) {
   6125         [webView _clearLayerSyncLoopObserver];
   6126         // AppKit may have disabled screen updates, thinking an upcoming window flush will re-enable them.
   6127         // In case setNeedsDisplayInRect() has prevented the window from needing to be flushed, re-enable screen
   6128         // updates here.
   6129         if (![window isFlushWindowDisabled])
   6130             [window _enableScreenUpdatesIfNeeded];
   6131     } else {
   6132         // Since the WebView does not need display, -viewWillDraw will not be called. Perform pending layout now,
   6133         // so that the layers draw with up-to-date layout.
   6134         [webView _viewWillDrawInternal];
   6135     }
   6136 }
   6137 
   6138 - (void)_scheduleCompositingLayerSync
   6139 {
   6140     CFRunLoopRef currentRunLoop = CFRunLoopGetCurrent();
   6141 
   6142     // Make sure we wake up the loop or the observer could be delayed until some other source fires.
   6143     CFRunLoopWakeUp(currentRunLoop);
   6144 
   6145     if (_private->layerSyncRunLoopObserver)
   6146         return;
   6147 
   6148     // Run after AppKit does its window update. If we do any painting, we'll commit
   6149     // layer changes from FrameView::paintContents(), otherwise we'll commit via
   6150     // _syncCompositingChanges when this observer fires.
   6151     const CFIndex runLoopOrder = NSDisplayWindowRunLoopOrdering + 1;
   6152 
   6153     // The WebView always outlives the observer, so no need to retain/release.
   6154     CFRunLoopObserverContext context = { 0, self, 0, 0, 0 };
   6155 
   6156     _private->layerSyncRunLoopObserver = CFRunLoopObserverCreate(NULL,
   6157         kCFRunLoopBeforeWaiting | kCFRunLoopExit, true /* repeats */,
   6158         runLoopOrder, layerSyncRunLoopObserverCallBack, &context);
   6159 
   6160     CFRunLoopAddObserver(currentRunLoop, _private->layerSyncRunLoopObserver, kCFRunLoopCommonModes);
   6161 }
   6162 
   6163 #endif
   6164 
   6165 #if ENABLE(VIDEO)
   6166 
   6167 - (void)_enterFullscreenForNode:(WebCore::Node*)node
   6168 {
   6169     ASSERT(node->hasTagName(WebCore::HTMLNames::videoTag));
   6170     HTMLMediaElement* videoElement = static_cast<HTMLMediaElement*>(node);
   6171 
   6172     if (_private->fullscreenController) {
   6173         if ([_private->fullscreenController mediaElement] == videoElement) {
   6174             // The backend may just warn us that the underlaying plaftormMovie()
   6175             // has changed. Just force an update.
   6176             [_private->fullscreenController setMediaElement:videoElement];
   6177             return; // No more to do.
   6178         }
   6179 
   6180         // First exit Fullscreen for the old mediaElement.
   6181         [_private->fullscreenController mediaElement]->exitFullscreen();
   6182         // This previous call has to trigger _exitFullscreen,
   6183         // which has to clear _private->fullscreenController.
   6184         ASSERT(!_private->fullscreenController);
   6185     }
   6186     if (!_private->fullscreenController) {
   6187         _private->fullscreenController = [[WebVideoFullscreenController alloc] init];
   6188         [_private->fullscreenController setMediaElement:videoElement];
   6189         [_private->fullscreenController enterFullscreen:[[self window] screen]];
   6190     }
   6191     else
   6192         [_private->fullscreenController setMediaElement:videoElement];
   6193 }
   6194 
   6195 - (void)_exitFullscreen
   6196 {
   6197     if (!_private->fullscreenController)
   6198         return;
   6199     [_private->fullscreenController exitFullscreen];
   6200     [_private->fullscreenController release];
   6201     _private->fullscreenController = nil;
   6202 }
   6203 
   6204 #endif
   6205 
   6206 #if ENABLE(FULLSCREEN_API)
   6207 - (BOOL)_supportsFullScreenForElement:(const WebCore::Element*)element withKeyboard:(BOOL)withKeyboard
   6208 {
   6209     if (withKeyboard)
   6210         return NO;
   6211 
   6212     if (![[WebPreferences standardPreferences] fullScreenEnabled])
   6213         return NO;
   6214 
   6215     // FIXME: If the element is in an IFrame, we should ensure it has
   6216     // an AllowsFullScreen=YES attribute before allowing fullscreen access.
   6217     return YES;
   6218 }
   6219 
   6220 - (void)_enterFullScreenForElement:(WebCore::Element*)element
   6221 {
   6222     if (!_private->newFullscreenController)
   6223         _private->newFullscreenController = [[WebFullScreenController alloc] init];
   6224 
   6225     [_private->newFullscreenController setElement:element];
   6226     [_private->newFullscreenController setWebView:self];
   6227     [_private->newFullscreenController enterFullscreen:[[self window] screen]];
   6228 }
   6229 
   6230 - (void)_exitFullScreenForElement:(WebCore::Element*)element
   6231 {
   6232     if (!_private->newFullscreenController)
   6233         return;
   6234     [_private->newFullscreenController exitFullscreen];
   6235 }
   6236 
   6237 - (void)_fullScreenRendererChanged:(WebCore::RenderBox*)renderer
   6238 {
   6239     if (!_private->newFullscreenController)
   6240         _private->newFullscreenController = [[WebFullScreenController alloc] init];
   6241     [_private->newFullscreenController setRenderer:renderer];
   6242 }
   6243 #endif
   6244 
   6245 #if ENABLE(GLIB_SUPPORT)
   6246 
   6247 static void glibContextIterationCallback(CFRunLoopObserverRef, CFRunLoopActivity, void*)
   6248 {
   6249     g_main_context_iteration(0, FALSE);
   6250 }
   6251 
   6252 - (void)_scheduleGlibContextIterations
   6253 {
   6254     if (_private->glibRunLoopObserver)
   6255         return;
   6256 
   6257     NSRunLoop* myRunLoop = [NSRunLoop currentRunLoop];
   6258 
   6259     // Create a run loop observer and attach it to the run loop.
   6260     CFRunLoopObserverContext context = {0, self, 0, 0, 0};
   6261     _private->glibRunLoopObserver = CFRunLoopObserverCreate(kCFAllocatorDefault, kCFRunLoopBeforeWaiting, YES, 0, &glibContextIterationCallback, &context);
   6262 
   6263     if (_private->glibRunLoopObserver) {
   6264         CFRunLoopRef cfLoop = [myRunLoop getCFRunLoop];
   6265         CFRunLoopAddObserver(cfLoop, _private->glibRunLoopObserver, kCFRunLoopDefaultMode);
   6266     }
   6267 
   6268 }
   6269 #endif
   6270 
   6271 
   6272 @end
   6273 
   6274 @implementation WebView (WebViewDeviceOrientation)
   6275 
   6276 - (void)_setDeviceOrientationProvider:(id<WebDeviceOrientationProvider>)deviceOrientationProvider
   6277 {
   6278     if (_private)
   6279         _private->m_deviceOrientationProvider = deviceOrientationProvider;
   6280 }
   6281 
   6282 - (id<WebDeviceOrientationProvider>)_deviceOrientationProvider
   6283 {
   6284     if (_private)
   6285         return _private->m_deviceOrientationProvider;
   6286     return nil;
   6287 }
   6288 
   6289 @end
   6290 
   6291 @implementation WebView (WebViewGeolocation)
   6292 
   6293 - (void)_setGeolocationProvider:(id<WebGeolocationProvider>)geolocationProvider
   6294 {
   6295     if (_private)
   6296         _private->_geolocationProvider = geolocationProvider;
   6297 }
   6298 
   6299 - (id<WebGeolocationProvider>)_geolocationProvider
   6300 {
   6301     if (_private)
   6302         return _private->_geolocationProvider;
   6303     return nil;
   6304 }
   6305 
   6306 - (void)_geolocationDidChangePosition:(WebGeolocationPosition *)position
   6307 {
   6308 #if ENABLE(CLIENT_BASED_GEOLOCATION)
   6309     if (_private && _private->page)
   6310         _private->page->geolocationController()->positionChanged(core(position));
   6311 #endif
   6312 }
   6313 
   6314 - (void)_geolocationDidFailWithError:(NSError *)error
   6315 {
   6316 #if ENABLE(CLIENT_BASED_GEOLOCATION)
   6317     if (_private && _private->page) {
   6318         RefPtr<GeolocationError> geolocatioError = GeolocationError::create(GeolocationError::PositionUnavailable, [error localizedDescription]);
   6319         _private->page->geolocationController()->errorOccurred(geolocatioError.get());
   6320     }
   6321 #endif
   6322 }
   6323 
   6324 @end
   6325 
   6326 @implementation WebView (WebViewPrivateStyleInfo)
   6327 
   6328 - (JSValueRef)_computedStyleIncludingVisitedInfo:(JSContextRef)context forElement:(JSValueRef)value
   6329 {
   6330     JSLock lock(SilenceAssertionsOnly);
   6331     ExecState* exec = toJS(context);
   6332     if (!value)
   6333         return JSValueMakeUndefined(context);
   6334     JSValue jsValue = toJS(exec, value);
   6335     if (!jsValue.inherits(&JSElement::s_info))
   6336         return JSValueMakeUndefined(context);
   6337     JSElement* jsElement = static_cast<JSElement*>(asObject(jsValue));
   6338     Element* element = jsElement->impl();
   6339     RefPtr<CSSComputedStyleDeclaration> style = computedStyle(element, true);
   6340     return toRef(exec, toJS(exec, jsElement->globalObject(), style.get()));
   6341 }
   6342 
   6343 @end
   6344 
   6345 @implementation WebView (WebViewPrivateNodesFromRect)
   6346 
   6347 - (JSValueRef)_nodesFromRect:(JSContextRef)context forDocument:(JSValueRef)value x:(int)x  y:(int)y top:(unsigned)top right:(unsigned)right bottom:(unsigned)bottom left:(unsigned)left ignoreClipping:(BOOL)ignoreClipping
   6348 {
   6349     JSLock lock(SilenceAssertionsOnly);
   6350     ExecState* exec = toJS(context);
   6351     if (!value)
   6352         return JSValueMakeUndefined(context);
   6353     JSValue jsValue = toJS(exec, value);
   6354     if (!jsValue.inherits(&JSDocument::s_info))
   6355         return JSValueMakeUndefined(context);
   6356     JSDocument* jsDocument = static_cast<JSDocument*>(asObject(jsValue));
   6357     Document* document = jsDocument->impl();
   6358     RefPtr<NodeList> nodes = document->nodesFromRect(x, y, top, right, bottom, left, ignoreClipping);
   6359     return toRef(exec, toJS(exec, jsDocument->globalObject(), nodes.get()));
   6360 }
   6361 
   6362 @end
   6363 
   6364 #ifdef BUILDING_ON_LEOPARD
   6365 
   6366 static IMP originalRecursivelyRemoveMailAttributesImp;
   6367 
   6368 static id objectElementDataAttribute(DOMHTMLObjectElement *self, SEL)
   6369 {
   6370     return [self getAttribute:@"data"];
   6371 }
   6372 
   6373 static void recursivelyRemoveMailAttributes(DOMNode *self, SEL selector, BOOL a, BOOL b, BOOL c)
   6374 {
   6375     // While inside this Mail function, change the behavior of -[DOMHTMLObjectElement data] back to what it used to be
   6376     // before we fixed a bug in it (see http://trac.webkit.org/changeset/30044 for that change).
   6377 
   6378     // It's a little bit strange to patch a method defined by WebKit, but it helps keep this workaround self-contained.
   6379 
   6380     Method methodToPatch = class_getInstanceMethod(objc_getRequiredClass("DOMHTMLObjectElement"), @selector(data));
   6381     IMP originalDataImp = method_setImplementation(methodToPatch, reinterpret_cast<IMP>(objectElementDataAttribute));
   6382     originalRecursivelyRemoveMailAttributesImp(self, selector, a, b, c);
   6383     method_setImplementation(methodToPatch, originalDataImp);
   6384 }
   6385 
   6386 #endif
   6387 
   6388 static void patchMailRemoveAttributesMethod()
   6389 {
   6390 #ifdef BUILDING_ON_LEOPARD
   6391     if (!WKAppVersionCheckLessThan(@"com.apple.mail", -1, 4.0))
   6392         return;
   6393     Method methodToPatch = class_getInstanceMethod(objc_getRequiredClass("DOMNode"), @selector(recursivelyRemoveMailAttributes:convertObjectsToImages:convertEditableElements:));
   6394     if (!methodToPatch)
   6395         return;
   6396     originalRecursivelyRemoveMailAttributesImp = method_setImplementation(methodToPatch, reinterpret_cast<IMP>(recursivelyRemoveMailAttributes));
   6397 #endif
   6398 }
   6399