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