2010-05-06 Anders Carlsson <andersca@apple.com>
[WebKit.git] / WebKit / mac / WebView / WebView.mm
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  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1.  Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer. 
11  * 2.  Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution. 
14  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15  *     its contributors may be used to endorse or promote products derived
16  *     from this software without specific prior written permission. 
17  *
18  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #import "WebViewInternal.h"
31 #import "WebViewData.h"
32
33 #import "DOMCSSStyleDeclarationInternal.h"
34 #import "DOMNodeInternal.h"
35 #import "DOMRangeInternal.h"
36 #import "WebBackForwardListInternal.h"
37 #import "WebBaseNetscapePluginView.h"
38 #import "WebCache.h"
39 #import "WebChromeClient.h"
40 #import "WebContextMenuClient.h"
41 #import "WebDOMOperationsPrivate.h"
42 #import "WebDataSourceInternal.h"
43 #import "WebDatabaseManagerInternal.h"
44 #import "WebDefaultEditingDelegate.h"
45 #import "WebDefaultPolicyDelegate.h"
46 #import "WebDefaultUIDelegate.h"
47 #import "WebDelegateImplementationCaching.h"
48 #import "WebDocument.h"
49 #import "WebDocumentInternal.h"
50 #import "WebDownload.h"
51 #import "WebDownloadInternal.h"
52 #import "WebDragClient.h"
53 #import "WebDynamicScrollBarsViewInternal.h"
54 #import "WebEditingDelegate.h"
55 #import "WebEditorClient.h"
56 #import "WebFormDelegatePrivate.h"
57 #import "WebFrameInternal.h"
58 #import "WebFrameViewInternal.h"
59 #import "WebGeolocationControllerClient.h"
60 #import "WebGeolocationPositionInternal.h"
61 #import "WebHTMLRepresentation.h"
62 #import "WebHTMLViewInternal.h"
63 #import "WebHistoryItemInternal.h"
64 #import "WebIconDatabaseInternal.h"
65 #import "WebInspector.h"
66 #import "WebInspectorClient.h"
67 #import "WebKitErrors.h"
68 #import "WebKitLogging.h"
69 #import "WebKitNSStringExtras.h"
70 #import "WebKitStatisticsPrivate.h"
71 #import "WebKitSystemBits.h"
72 #import "WebKitVersionChecks.h"
73 #import "WebLocalizableStrings.h"
74 #import "WebNSDataExtras.h"
75 #import "WebNSDataExtrasPrivate.h"
76 #import "WebNSDictionaryExtras.h"
77 #import "WebNSEventExtras.h"
78 #import "WebNSObjectExtras.h"
79 #import "WebNSPasteboardExtras.h"
80 #import "WebNSPrintOperationExtras.h"
81 #import "WebNSURLExtras.h"
82 #import "WebNSURLRequestExtras.h"
83 #import "WebNSUserDefaultsExtras.h"
84 #import "WebNSViewExtras.h"
85 #import "WebNodeHighlight.h"
86 #import "WebPDFView.h"
87 #import "WebPanelAuthenticationHandler.h"
88 #import "WebPasteboardHelper.h"
89 #import "WebPluginDatabase.h"
90 #import "WebPluginHalterClient.h"
91 #import "WebPolicyDelegate.h"
92 #import "WebPreferenceKeysPrivate.h"
93 #import "WebPreferencesPrivate.h"
94 #import "WebScriptDebugDelegate.h"
95 #import "WebScriptWorldInternal.h"
96 #import "WebSystemInterface.h"
97 #import "WebTextCompletionController.h"
98 #import "WebTextIterator.h"
99 #import "WebUIDelegate.h"
100 #import "WebUIDelegatePrivate.h"
101 #import "WebVideoFullscreenController.h"
102 #import <CoreFoundation/CFSet.h>
103 #import <Foundation/NSURLConnection.h>
104 #import <JavaScriptCore/APICast.h>
105 #import <JavaScriptCore/JSValueRef.h>
106 #import <WebCore/ApplicationCacheStorage.h>
107 #import <WebCore/BackForwardList.h>
108 #import <WebCore/Cache.h>
109 #import <WebCore/ColorMac.h>
110 #import <WebCore/CSSComputedStyleDeclaration.h>
111 #import <WebCore/Cursor.h>
112 #import <WebCore/Database.h>
113 #import <WebCore/Document.h>
114 #import <WebCore/DocumentLoader.h>
115 #import <WebCore/DragController.h>
116 #import <WebCore/DragData.h>
117 #import <WebCore/Editor.h>
118 #import <WebCore/EventHandler.h>
119 #import <WebCore/ExceptionHandlers.h>
120 #import <WebCore/FocusController.h>
121 #import <WebCore/Frame.h>
122 #import <WebCore/FrameLoader.h>
123 #import <WebCore/FrameTree.h>
124 #import <WebCore/FrameView.h>
125 #import <WebCore/GCController.h>
126 #import <WebCore/HTMLMediaElement.h>
127 #import <WebCore/HTMLNames.h>
128 #import <WebCore/HistoryItem.h>
129 #import <WebCore/IconDatabase.h>
130 #import <WebCore/JSCSSStyleDeclaration.h>
131 #import <WebCore/JSElement.h>
132 #import <WebCore/Logging.h>
133 #import <WebCore/MIMETypeRegistry.h>
134 #import <WebCore/Page.h>
135 #import <WebCore/PageCache.h>
136 #import <WebCore/PageGroup.h>
137 #import <WebCore/PlatformMouseEvent.h>
138 #import <WebCore/ProgressTracker.h>
139 #import <WebCore/RenderWidget.h>
140 #import <WebCore/ResourceHandle.h>
141 #import <WebCore/RuntimeApplicationChecks.h>
142 #import <WebCore/ScriptController.h>
143 #import <WebCore/ScriptValue.h>
144 #import <WebCore/SecurityOrigin.h>
145 #import <WebCore/SelectionController.h>
146 #import <WebCore/Settings.h>
147 #import <WebCore/TextResourceDecoder.h>
148 #import <WebCore/ThreadCheck.h>
149 #import <WebCore/WebCoreObjCExtras.h>
150 #import <WebCore/WebCoreView.h>
151 #import <WebCore/Widget.h>
152 #import <WebKit/DOM.h>
153 #import <WebKit/DOMExtensions.h>
154 #import <WebKit/DOMPrivate.h>
155 #import <WebKitSystemInterface.h>
156 #import <mach-o/dyld.h>
157 #import <objc/objc-auto.h>
158 #import <objc/objc-runtime.h>
159 #import <runtime/ArrayPrototype.h>
160 #import <runtime/DateInstance.h>
161 #import <runtime/InitializeThreading.h>
162 #import <runtime/JSLock.h>
163 #import <runtime/JSValue.h>
164 #import <wtf/Assertions.h>
165 #import <wtf/HashTraits.h>
166 #import <wtf/RefCountedLeakCounter.h>
167 #import <wtf/RefPtr.h>
168 #import <wtf/StdLibExtras.h>
169 #import <wtf/Threading.h>
170
171 #if ENABLE(DASHBOARD_SUPPORT)
172 #import <WebKit/WebDashboardRegion.h>
173 #endif
174
175 #if ENABLE(CLIENT_BASED_GEOLOCATION)
176 #import <WebCore/GeolocationController.h>
177 #import <WebCore/GeolocationError.h>
178 #endif
179
180 @interface NSSpellChecker (WebNSSpellCheckerDetails)
181 - (void)_preflightChosenSpellServer;
182 @end
183
184 @interface NSView (WebNSViewDetails)
185 - (NSView *)_hitTest:(NSPoint *)aPoint dragTypes:(NSSet *)types;
186 - (void)_autoscrollForDraggingInfo:(id)dragInfo timeDelta:(NSTimeInterval)repeatDelta;
187 - (BOOL)_shouldAutoscrollForDraggingInfo:(id)dragInfo;
188 @end
189
190 @interface NSWindow (WebNSWindowDetails) 
191 - (id)_oldFirstResponderBeforeBecoming;
192 - (void)_enableScreenUpdatesIfNeeded;
193 @end
194
195 using namespace WebCore;
196 using namespace JSC;
197
198 #if defined(__ppc__) || defined(__ppc64__)
199 #define PROCESSOR "PPC"
200 #elif defined(__i386__) || defined(__x86_64__)
201 #define PROCESSOR "Intel"
202 #else
203 #error Unknown architecture
204 #endif
205
206 #define FOR_EACH_RESPONDER_SELECTOR(macro) \
207 macro(alignCenter) \
208 macro(alignJustified) \
209 macro(alignLeft) \
210 macro(alignRight) \
211 macro(capitalizeWord) \
212 macro(centerSelectionInVisibleArea) \
213 macro(changeAttributes) \
214 macro(changeBaseWritingDirection) \
215 macro(changeBaseWritingDirectionToLTR) \
216 macro(changeBaseWritingDirectionToRTL) \
217 macro(changeColor) \
218 macro(changeDocumentBackgroundColor) \
219 macro(changeFont) \
220 macro(changeSpelling) \
221 macro(checkSpelling) \
222 macro(complete) \
223 macro(copy) \
224 macro(copyFont) \
225 macro(cut) \
226 macro(delete) \
227 macro(deleteBackward) \
228 macro(deleteBackwardByDecomposingPreviousCharacter) \
229 macro(deleteForward) \
230 macro(deleteToBeginningOfLine) \
231 macro(deleteToBeginningOfParagraph) \
232 macro(deleteToEndOfLine) \
233 macro(deleteToEndOfParagraph) \
234 macro(deleteToMark) \
235 macro(deleteWordBackward) \
236 macro(deleteWordForward) \
237 macro(ignoreSpelling) \
238 macro(indent) \
239 macro(insertBacktab) \
240 macro(insertLineBreak) \
241 macro(insertNewline) \
242 macro(insertNewlineIgnoringFieldEditor) \
243 macro(insertParagraphSeparator) \
244 macro(insertTab) \
245 macro(insertTabIgnoringFieldEditor) \
246 macro(lowercaseWord) \
247 macro(makeBaseWritingDirectionLeftToRight) \
248 macro(makeBaseWritingDirectionRightToLeft) \
249 macro(makeTextWritingDirectionLeftToRight) \
250 macro(makeTextWritingDirectionNatural) \
251 macro(makeTextWritingDirectionRightToLeft) \
252 macro(moveBackward) \
253 macro(moveBackwardAndModifySelection) \
254 macro(moveDown) \
255 macro(moveDownAndModifySelection) \
256 macro(moveForward) \
257 macro(moveForwardAndModifySelection) \
258 macro(moveLeft) \
259 macro(moveLeftAndModifySelection) \
260 macro(moveParagraphBackwardAndModifySelection) \
261 macro(moveParagraphForwardAndModifySelection) \
262 macro(moveRight) \
263 macro(moveRightAndModifySelection) \
264 macro(moveToBeginningOfDocument) \
265 macro(moveToBeginningOfDocumentAndModifySelection) \
266 macro(moveToBeginningOfLine) \
267 macro(moveToBeginningOfLineAndModifySelection) \
268 macro(moveToBeginningOfParagraph) \
269 macro(moveToBeginningOfParagraphAndModifySelection) \
270 macro(moveToBeginningOfSentence) \
271 macro(moveToBeginningOfSentenceAndModifySelection) \
272 macro(moveToEndOfDocument) \
273 macro(moveToEndOfDocumentAndModifySelection) \
274 macro(moveToEndOfLine) \
275 macro(moveToEndOfLineAndModifySelection) \
276 macro(moveToEndOfParagraph) \
277 macro(moveToEndOfParagraphAndModifySelection) \
278 macro(moveToEndOfSentence) \
279 macro(moveToEndOfSentenceAndModifySelection) \
280 macro(moveToLeftEndOfLine) \
281 macro(moveToLeftEndOfLineAndModifySelection) \
282 macro(moveToRightEndOfLine) \
283 macro(moveToRightEndOfLineAndModifySelection) \
284 macro(moveUp) \
285 macro(moveUpAndModifySelection) \
286 macro(moveWordBackward) \
287 macro(moveWordBackwardAndModifySelection) \
288 macro(moveWordForward) \
289 macro(moveWordForwardAndModifySelection) \
290 macro(moveWordLeft) \
291 macro(moveWordLeftAndModifySelection) \
292 macro(moveWordRight) \
293 macro(moveWordRightAndModifySelection) \
294 macro(outdent) \
295 macro(orderFrontSubstitutionsPanel) \
296 macro(pageDown) \
297 macro(pageDownAndModifySelection) \
298 macro(pageUp) \
299 macro(pageUpAndModifySelection) \
300 macro(paste) \
301 macro(pasteAsPlainText) \
302 macro(pasteAsRichText) \
303 macro(pasteFont) \
304 macro(performFindPanelAction) \
305 macro(scrollLineDown) \
306 macro(scrollLineUp) \
307 macro(scrollPageDown) \
308 macro(scrollPageUp) \
309 macro(scrollToBeginningOfDocument) \
310 macro(scrollToEndOfDocument) \
311 macro(selectAll) \
312 macro(selectLine) \
313 macro(selectParagraph) \
314 macro(selectSentence) \
315 macro(selectToMark) \
316 macro(selectWord) \
317 macro(setMark) \
318 macro(showGuessPanel) \
319 macro(startSpeaking) \
320 macro(stopSpeaking) \
321 macro(subscript) \
322 macro(superscript) \
323 macro(swapWithMark) \
324 macro(takeFindStringFromSelection) \
325 macro(toggleBaseWritingDirection) \
326 macro(transpose) \
327 macro(underline) \
328 macro(unscript) \
329 macro(uppercaseWord) \
330 macro(yank) \
331 macro(yankAndSelect) \
332
333 #define WebKitOriginalTopPrintingMarginKey @"WebKitOriginalTopMargin"
334 #define WebKitOriginalBottomPrintingMarginKey @"WebKitOriginalBottomMargin"
335
336 #define KeyboardUIModeDidChangeNotification @"com.apple.KeyboardUIModeDidChange"
337 #define AppleKeyboardUIMode CFSTR("AppleKeyboardUIMode")
338 #define UniversalAccessDomain CFSTR("com.apple.universalaccess")
339
340 static BOOL s_didSetCacheModel;
341 static WebCacheModel s_cacheModel = WebCacheModelDocumentViewer;
342
343 #ifndef NDEBUG
344 static const char webViewIsOpen[] = "At least one WebView is still open.";
345 #endif
346
347 @interface NSObject (WebValidateWithoutDelegate)
348 - (BOOL)validateUserInterfaceItemWithoutDelegate:(id <NSValidatedUserInterfaceItem>)item;
349 @end
350
351 @interface _WebSafeForwarder : NSObject
352 {
353     id target; // Non-retained. Don't retain delegates.
354     id defaultTarget;
355     BOOL catchExceptions;
356 }
357 - (id)initWithTarget:(id)target defaultTarget:(id)defaultTarget catchExceptions:(BOOL)catchExceptions;
358 @end
359
360 @interface WebView (WebFileInternal)
361 - (BOOL)_isLoading;
362 - (WebFrameView *)_frameViewAtWindowPoint:(NSPoint)point;
363 - (WebFrame *)_focusedFrame;
364 + (void)_preflightSpellChecker;
365 - (BOOL)_continuousCheckingAllowed;
366 - (NSResponder *)_responderForResponderOperations;
367 #if USE(ACCELERATED_COMPOSITING)
368 - (void)_clearLayerSyncLoopObserver;
369 #endif
370 @end
371
372 static void patchMailRemoveAttributesMethod();
373
374 NSString *WebElementDOMNodeKey =            @"WebElementDOMNode";
375 NSString *WebElementFrameKey =              @"WebElementFrame";
376 NSString *WebElementImageKey =              @"WebElementImage";
377 NSString *WebElementImageAltStringKey =     @"WebElementImageAltString";
378 NSString *WebElementImageRectKey =          @"WebElementImageRect";
379 NSString *WebElementImageURLKey =           @"WebElementImageURL";
380 NSString *WebElementIsSelectedKey =         @"WebElementIsSelected";
381 NSString *WebElementLinkLabelKey =          @"WebElementLinkLabel";
382 NSString *WebElementLinkTargetFrameKey =    @"WebElementTargetFrame";
383 NSString *WebElementLinkTitleKey =          @"WebElementLinkTitle";
384 NSString *WebElementLinkURLKey =            @"WebElementLinkURL";
385 NSString *WebElementSpellingToolTipKey =    @"WebElementSpellingToolTip";
386 NSString *WebElementTitleKey =              @"WebElementTitle";
387 NSString *WebElementLinkIsLiveKey =         @"WebElementLinkIsLive";
388 NSString *WebElementIsInScrollBarKey =      @"WebElementIsInScrollBar";
389 NSString *WebElementIsContentEditableKey =  @"WebElementIsContentEditableKey";
390
391 NSString *WebViewProgressStartedNotification =          @"WebProgressStartedNotification";
392 NSString *WebViewProgressEstimateChangedNotification =  @"WebProgressEstimateChangedNotification";
393 NSString *WebViewProgressFinishedNotification =         @"WebProgressFinishedNotification";
394
395 NSString * const WebViewDidBeginEditingNotification =         @"WebViewDidBeginEditingNotification";
396 NSString * const WebViewDidChangeNotification =               @"WebViewDidChangeNotification";
397 NSString * const WebViewDidEndEditingNotification =           @"WebViewDidEndEditingNotification";
398 NSString * const WebViewDidChangeTypingStyleNotification =    @"WebViewDidChangeTypingStyleNotification";
399 NSString * const WebViewDidChangeSelectionNotification =      @"WebViewDidChangeSelectionNotification";
400
401 enum { WebViewVersion = 4 };
402
403 #define timedLayoutSize 4096
404
405 static NSMutableSet *schemesWithRepresentationsSet;
406
407 NSString *_WebCanGoBackKey =            @"canGoBack";
408 NSString *_WebCanGoForwardKey =         @"canGoForward";
409 NSString *_WebEstimatedProgressKey =    @"estimatedProgress";
410 NSString *_WebIsLoadingKey =            @"isLoading";
411 NSString *_WebMainFrameIconKey =        @"mainFrameIcon";
412 NSString *_WebMainFrameTitleKey =       @"mainFrameTitle";
413 NSString *_WebMainFrameURLKey =         @"mainFrameURL";
414 NSString *_WebMainFrameDocumentKey =    @"mainFrameDocument";
415
416 NSString *_WebViewDidStartAcceleratedCompositingNotification = @"_WebViewDidStartAcceleratedCompositing";
417
418 @interface WebProgressItem : NSObject
419 {
420 @public
421     long long bytesReceived;
422     long long estimatedLength;
423 }
424 @end
425
426 @implementation WebProgressItem
427 @end
428
429 static BOOL continuousSpellCheckingEnabled;
430 #ifndef BUILDING_ON_TIGER
431 static BOOL grammarCheckingEnabled;
432 #endif
433 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
434 static BOOL automaticQuoteSubstitutionEnabled;
435 static BOOL automaticLinkDetectionEnabled;
436 static BOOL automaticDashSubstitutionEnabled;
437 static BOOL automaticTextReplacementEnabled;
438 static BOOL automaticSpellingCorrectionEnabled;
439 #endif
440
441 @implementation WebView (AllWebViews)
442
443 static CFSetCallBacks NonRetainingSetCallbacks = {
444     0,
445     NULL,
446     NULL,
447     CFCopyDescription,
448     CFEqual,
449     CFHash
450 };
451
452 static CFMutableSetRef allWebViewsSet;
453
454 + (void)_makeAllWebViewsPerformSelector:(SEL)selector
455 {
456     if (!allWebViewsSet)
457         return;
458
459     [(NSMutableSet *)allWebViewsSet makeObjectsPerformSelector:selector];
460 }
461
462 - (void)_removeFromAllWebViewsSet
463 {
464     if (allWebViewsSet)
465         CFSetRemoveValue(allWebViewsSet, self);
466 }
467
468 - (void)_addToAllWebViewsSet
469 {
470     if (!allWebViewsSet)
471         allWebViewsSet = CFSetCreateMutable(NULL, 0, &NonRetainingSetCallbacks);
472
473     CFSetSetValue(allWebViewsSet, self);
474 }
475
476 @end
477
478 @implementation WebView (WebPrivate)
479
480 static inline int callGestalt(OSType selector)
481 {
482     SInt32 value = 0;
483     Gestalt(selector, &value);
484     return value;
485 }
486
487 // Uses underscores instead of dots because if "4." ever appears in a user agent string, old DHTML libraries treat it as Netscape 4.
488 static NSString *createMacOSXVersionString()
489 {
490     // Can't use -[NSProcessInfo operatingSystemVersionString] because it has too much stuff we don't want.
491     int major = callGestalt(gestaltSystemVersionMajor);
492     ASSERT(major);
493
494     int minor = callGestalt(gestaltSystemVersionMinor);
495     int bugFix = callGestalt(gestaltSystemVersionBugFix);
496     if (bugFix)
497         return [[NSString alloc] initWithFormat:@"%d_%d_%d", major, minor, bugFix];
498     if (minor)
499         return [[NSString alloc] initWithFormat:@"%d_%d", major, minor];
500     return [[NSString alloc] initWithFormat:@"%d", major];
501 }
502
503 static NSString *createUserVisibleWebKitVersionString()
504 {
505     // If the version is 4 digits long or longer, then the first digit represents
506     // the version of the OS. Our user agent string should not include this first digit,
507     // so strip it off and report the rest as the version. <rdar://problem/4997547>
508     NSString *fullVersion = [[NSBundle bundleForClass:[WebView class]] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey];
509     NSRange nonDigitRange = [fullVersion rangeOfCharacterFromSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]];
510     if (nonDigitRange.location == NSNotFound && [fullVersion length] >= 4)
511         return [[fullVersion substringFromIndex:1] copy];
512     if (nonDigitRange.location != NSNotFound && nonDigitRange.location >= 4)
513         return [[fullVersion substringFromIndex:1] copy];
514     return [fullVersion copy];
515 }
516
517 + (NSString *)_standardUserAgentWithApplicationName:(NSString *)applicationName
518 {
519     // Note: Do *not* move the initialization of osVersion nor webKitVersion into the declaration.
520     // Garbage collection won't correctly mark the global variable in that case <rdar://problem/5733674>.
521     static NSString *osVersion;
522     static NSString *webKitVersion;
523     if (!osVersion)
524         osVersion = createMacOSXVersionString();
525     if (!webKitVersion)
526         webKitVersion = createUserVisibleWebKitVersionString();
527     NSString *language = [NSUserDefaults _webkit_preferredLanguageCode];
528     if ([applicationName length])
529         return [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; U; " PROCESSOR " Mac OS X %@; %@) AppleWebKit/%@ (KHTML, like Gecko) %@", osVersion, language, webKitVersion, applicationName];
530     return [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; U; " PROCESSOR " Mac OS X %@; %@) AppleWebKit/%@ (KHTML, like Gecko)", osVersion, language, webKitVersion];
531 }
532
533 static void WebKitInitializeApplicationCachePathIfNecessary()
534 {
535 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
536     static BOOL initialized = NO;
537     if (initialized)
538         return;
539
540     NSString *appName = [[NSBundle mainBundle] bundleIdentifier];
541     if (!appName)
542         appName = [[NSProcessInfo processInfo] processName];
543     
544     ASSERT(appName);
545
546     NSString* cacheDir = [NSString _webkit_localCacheDirectoryWithBundleIdentifier:appName];
547
548     cacheStorage().setCacheDirectory(cacheDir);
549     initialized = YES;
550 #endif
551 }
552
553 static bool runningLeopardMail()
554 {
555 #ifdef BUILDING_ON_LEOPARD
556     return applicationIsAppleMail();
557 #endif
558     return NO;
559 }
560
561 static bool runningTigerMail()
562 {
563 #ifdef BUILDING_ON_TIGER
564     return applicationIsAppleMail();
565 #endif
566     return NO;    
567 }
568
569 static bool coreVideoHas7228836Fix()
570 {
571 #ifdef BUILDING_ON_LEOPARD
572     NSBundle* coreVideoFrameworkBundle = [NSBundle bundleWithPath:@"/System/Library/Frameworks/CoreVideo.framework"];
573     double version = [[coreVideoFrameworkBundle objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey] doubleValue];
574     return (version >= 48);
575 #endif
576     return true;
577 }
578
579 static bool shouldEnableLoadDeferring()
580 {
581     return !applicationIsAdobeInstaller();
582 }
583
584 - (void)_dispatchPendingLoadRequests
585 {
586     cache()->loader()->servePendingRequests();
587 }
588
589 - (void)_registerDraggedTypes
590 {
591     NSArray *editableTypes = [WebHTMLView _insertablePasteboardTypes];
592     NSArray *URLTypes = [NSPasteboard _web_dragTypesForURL];
593     NSMutableSet *types = [[NSMutableSet alloc] initWithArray:editableTypes];
594     [types addObjectsFromArray:URLTypes];
595     [self registerForDraggedTypes:[types allObjects]];
596     [types release];
597 }
598
599 - (BOOL)_usesDocumentViews
600 {
601     return _private->usesDocumentViews;
602 }
603
604 - (void)_commonInitializationWithFrameName:(NSString *)frameName groupName:(NSString *)groupName usesDocumentViews:(BOOL)usesDocumentViews
605 {
606     WebCoreThreadViolationCheckRoundTwo();
607
608 #ifndef NDEBUG
609     WTF::RefCountedLeakCounter::suppressMessages(webViewIsOpen);
610 #endif
611     
612     WebPreferences *standardPreferences = [WebPreferences standardPreferences];
613     [standardPreferences willAddToWebView];
614
615     _private->preferences = [standardPreferences retain];
616     _private->catchesDelegateExceptions = YES;
617     _private->mainFrameDocumentReady = NO;
618     _private->drawsBackground = YES;
619     _private->backgroundColor = [[NSColor colorWithDeviceWhite:1 alpha:1] retain];
620     _private->usesDocumentViews = usesDocumentViews;
621     _private->includesFlattenedCompositingLayersWhenDrawingToBitmap = YES;
622
623     WebFrameView *frameView = nil;
624     if (_private->usesDocumentViews) {
625         NSRect f = [self frame];
626         frameView = [[WebFrameView alloc] initWithFrame: NSMakeRect(0,0,f.size.width,f.size.height)];
627         [frameView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
628         [self addSubview:frameView];
629         [frameView release];
630     }
631
632     static bool didOneTimeInitialization = false;
633     if (!didOneTimeInitialization) {
634         WebKitInitializeLoggingChannelsIfNecessary();
635         WebCore::InitializeLoggingChannelsIfNecessary();
636         [WebHistoryItem initWindowWatcherIfNecessary];
637 #if ENABLE(DATABASE)
638         WebKitInitializeDatabasesIfNecessary();
639 #endif
640         WebKitInitializeApplicationCachePathIfNecessary();
641         patchMailRemoveAttributesMethod();
642         didOneTimeInitialization = true;
643     }
644
645 #if ENABLE(CLIENT_BASED_GEOLOCATION)
646     WebGeolocationControllerClient* geolocationControllerClient = new WebGeolocationControllerClient(self);
647 #else
648     WebGeolocationControllerClient* geolocationControllerClient = 0;
649 #endif
650     _private->page = new Page(new WebChromeClient(self), new WebContextMenuClient(self), new WebEditorClient(self), new WebDragClient(self), new WebInspectorClient(self), new WebPluginHalterClient(self), geolocationControllerClient);
651
652     _private->page->setCanStartMedia([self window]);
653     _private->page->settings()->setLocalStorageDatabasePath([[self preferences] _localStorageDatabasePath]);
654
655     [WebFrame _createMainFrameWithPage:_private->page frameName:frameName frameView:frameView];
656
657 #ifndef BUILDING_ON_TIGER
658     NSRunLoop *runLoop = [NSRunLoop mainRunLoop];
659 #else
660     NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
661 #endif
662
663     if (WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_LOADING_DURING_COMMON_RUNLOOP_MODES))
664         [self scheduleInRunLoop:runLoop forMode:(NSString *)kCFRunLoopCommonModes];
665     else
666         [self scheduleInRunLoop:runLoop forMode:NSDefaultRunLoopMode];
667
668     [self _addToAllWebViewsSet];
669     [self setGroupName:groupName];
670     
671     // If there's already a next key view (e.g., from a nib), wire it up to our
672     // contained frame view. In any case, wire our next key view up to the our
673     // contained frame view. This works together with our becomeFirstResponder 
674     // and setNextKeyView overrides.
675     NSView *nextKeyView = [self nextKeyView];
676     if (nextKeyView && nextKeyView != frameView)
677         [frameView setNextKeyView:nextKeyView];
678     [super setNextKeyView:frameView];
679
680     if ([[self class] shouldIncludeInWebKitStatistics])
681         ++WebViewCount;
682
683     [self _registerDraggedTypes];
684
685     WebPreferences *prefs = [self preferences];
686     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:)
687                                                  name:WebPreferencesChangedNotification object:prefs];
688
689     // Post a notification so the WebCore settings update.
690     [[self preferences] _postPreferencesChangesNotification];
691
692     if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_LOCAL_RESOURCE_SECURITY_RESTRICTION)) {
693         // Originally, we allowed all local loads.
694         SecurityOrigin::setLocalLoadPolicy(SecurityOrigin::AllowLocalLoadsForAll);
695     } else if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_MORE_STRICT_LOCAL_RESOURCE_SECURITY_RESTRICTION)) {
696         // Later, we allowed local loads for local URLs and documents loaded
697         // with substitute data.
698         SecurityOrigin::setLocalLoadPolicy(SecurityOrigin::AllowLocalLoadsForLocalAndSubstituteData);
699     }
700
701     if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_CONTENT_SNIFFING_FOR_FILE_URLS))
702         ResourceHandle::forceContentSniffing();
703 }
704
705 - (id)_initWithFrame:(NSRect)f frameName:(NSString *)frameName groupName:(NSString *)groupName usesDocumentViews:(BOOL)usesDocumentViews
706 {
707     self = [super initWithFrame:f];
708     if (!self)
709         return nil;
710
711 #ifdef ENABLE_WEBKIT_UNSET_DYLD_FRAMEWORK_PATH
712     // DYLD_FRAMEWORK_PATH is used so Safari will load the development version of WebKit, which
713     // may not work with other WebKit applications.  Unsetting DYLD_FRAMEWORK_PATH removes the
714     // need for Safari to unset it to prevent it from being passed to applications it launches.
715     // Unsetting it when a WebView is first created is as good a place as any.
716     // See <http://bugs.webkit.org/show_bug.cgi?id=4286> for more details.
717     if (getenv("WEBKIT_UNSET_DYLD_FRAMEWORK_PATH")) {
718         unsetenv("DYLD_FRAMEWORK_PATH");
719         unsetenv("WEBKIT_UNSET_DYLD_FRAMEWORK_PATH");
720     }
721 #endif
722
723     _private = [[WebViewPrivate alloc] init];
724     [self _commonInitializationWithFrameName:frameName groupName:groupName usesDocumentViews:usesDocumentViews];
725     [self setMaintainsBackForwardList: YES];
726     return self;
727 }
728
729 - (BOOL)_mustDrawUnionedRect:(NSRect)rect singleRects:(const NSRect *)rects count:(NSInteger)count
730 {
731     // If count == 0 here, use the rect passed in for drawing. This is a workaround for:
732     // <rdar://problem/3908282> REGRESSION (Mail): No drag image dragging selected text in Blot and Mail
733     // The reason for the workaround is that this method is called explicitly from the code
734     // to generate a drag image, and at that time, getRectsBeingDrawn:count: will return a zero count.
735     const int cRectThreshold = 10;
736     const float cWastedSpaceThreshold = 0.75f;
737     BOOL useUnionedRect = (count <= 1) || (count > cRectThreshold);
738     if (!useUnionedRect) {
739         // Attempt to guess whether or not we should use the unioned rect or the individual rects.
740         // We do this by computing the percentage of "wasted space" in the union.  If that wasted space
741         // is too large, then we will do individual rect painting instead.
742         float unionPixels = (rect.size.width * rect.size.height);
743         float singlePixels = 0;
744         for (int i = 0; i < count; ++i)
745             singlePixels += rects[i].size.width * rects[i].size.height;
746         float wastedSpace = 1 - (singlePixels / unionPixels);
747         if (wastedSpace <= cWastedSpaceThreshold)
748             useUnionedRect = YES;
749     }
750     return useUnionedRect;
751 }
752
753 - (void)drawSingleRect:(NSRect)rect
754 {
755     ASSERT(!_private->usesDocumentViews);
756     
757     [NSGraphicsContext saveGraphicsState];
758     NSRectClip(rect);
759
760     @try {
761         [[self mainFrame] _drawRect:rect contentsOnly:NO];
762
763         [[self _UIDelegateForwarder] webView:self didDrawRect:rect];
764
765         if (WebNodeHighlight *currentHighlight = [self currentNodeHighlight])
766             [currentHighlight setNeedsUpdateInTargetViewRect:rect];
767
768         [NSGraphicsContext restoreGraphicsState];
769     } @catch (NSException *localException) {
770         [NSGraphicsContext restoreGraphicsState];
771         LOG_ERROR("Exception caught while drawing: %@", localException);
772         [localException raise];
773     }
774 }
775
776 - (BOOL)isFlipped 
777 {
778     return _private && !_private->usesDocumentViews;
779 }
780
781 - (void)setFrameSize:(NSSize)size
782 {
783     if (!_private->usesDocumentViews && !NSEqualSizes(_private->lastLayoutSize, size)) {
784         Frame* frame = [self _mainCoreFrame];
785         // FIXME: Viewless WebKit is broken with Safari banners (e.g., the Find banner).  We'll have to figure out a way for
786         // Safari to communicate that this space is being consumed.  For WebKit with document views, there's no
787         // need to do an explicit resize, since WebFrameViews have auto resizing turned on and will handle changing
788         // their bounds automatically. See <rdar://problem/6835573> for details.
789         frame->view()->resize(IntSize(size));
790         frame->view()->setNeedsLayout();
791         [self setNeedsDisplay:YES];
792         _private->lastLayoutSize = size;
793     }
794
795     [super setFrameSize:size];
796 }
797
798 #if USE(ACCELERATED_COMPOSITING) || !defined(BUILDING_ON_TIGER)
799
800 - (void)_viewWillDrawInternal
801 {
802     Frame* frame = [self _mainCoreFrame];
803     if (frame && frame->view())
804         frame->view()->layoutIfNeededRecursive();
805 }
806
807 #endif
808
809 #ifndef BUILDING_ON_TIGER
810
811 - (void)viewWillDraw
812 {
813     if (!_private->usesDocumentViews)
814         [self _viewWillDrawInternal];
815     [super viewWillDraw];
816 }
817
818 #endif
819
820
821 - (void)drawRect:(NSRect)rect
822 {
823     if (_private->usesDocumentViews)
824         return [super drawRect:rect];
825     
826     ASSERT_MAIN_THREAD();
827
828     const NSRect *rects;
829     NSInteger count;
830     [self getRectsBeingDrawn:&rects count:&count];
831
832     
833     if ([self _mustDrawUnionedRect:rect singleRects:rects count:count])
834         [self drawSingleRect:rect];
835     else
836         for (int i = 0; i < count; ++i)
837             [self drawSingleRect:rects[i]];
838 }
839
840 + (NSArray *)_supportedMIMETypes
841 {
842     // Load the plug-in DB allowing plug-ins to install types.
843     [WebPluginDatabase sharedDatabase];
844     return [[WebFrameView _viewTypesAllowImageTypeOmission:NO] allKeys];
845 }
846
847 + (NSArray *)_supportedFileExtensions
848 {
849     NSMutableSet *extensions = [[NSMutableSet alloc] init];
850     NSArray *MIMETypes = [self _supportedMIMETypes];
851     NSEnumerator *enumerator = [MIMETypes objectEnumerator];
852     NSString *MIMEType;
853     while ((MIMEType = [enumerator nextObject]) != nil) {
854         NSArray *extensionsForType = WKGetExtensionsForMIMEType(MIMEType);
855         if (extensionsForType) {
856             [extensions addObjectsFromArray:extensionsForType];
857         }
858     }
859     NSArray *uniqueExtensions = [extensions allObjects];
860     [extensions release];
861     return uniqueExtensions;
862 }
863
864 static NSMutableSet *knownPluginMIMETypes()
865 {
866     static NSMutableSet *mimeTypes = [[NSMutableSet alloc] init];
867     
868     return mimeTypes;
869 }
870
871 + (void)_registerPluginMIMEType:(NSString *)MIMEType
872 {
873     [WebView registerViewClass:[WebHTMLView class] representationClass:[WebHTMLRepresentation class] forMIMEType:MIMEType];
874     [knownPluginMIMETypes() addObject:MIMEType];
875 }
876
877 + (void)_unregisterPluginMIMEType:(NSString *)MIMEType
878 {
879     [self _unregisterViewClassAndRepresentationClassForMIMEType:MIMEType];
880     [knownPluginMIMETypes() removeObject:MIMEType];
881 }
882
883 + (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType allowingPlugins:(BOOL)allowPlugins
884 {
885     MIMEType = [MIMEType lowercaseString];
886     Class viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:YES] _webkit_objectForMIMEType:MIMEType];
887     Class repClass = [[WebDataSource _repTypesAllowImageTypeOmission:YES] _webkit_objectForMIMEType:MIMEType];
888
889     if (!viewClass || !repClass || [[WebPDFView supportedMIMETypes] containsObject:MIMEType]) {
890         // Our optimization to avoid loading the plug-in DB and image types for the HTML case failed.
891
892         if (allowPlugins) {
893             // Load the plug-in DB allowing plug-ins to install types.
894             [WebPluginDatabase sharedDatabase];
895         }
896
897         // Load the image types and get the view class and rep class. This should be the fullest picture of all handled types.
898         viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:NO] _webkit_objectForMIMEType:MIMEType];
899         repClass = [[WebDataSource _repTypesAllowImageTypeOmission:NO] _webkit_objectForMIMEType:MIMEType];
900     }
901     
902     if (viewClass && repClass) {
903         if (viewClass == [WebHTMLView class] && repClass == [WebHTMLRepresentation class]) {
904             // Special-case WebHTMLView for text types that shouldn't be shown.
905             if ([[WebHTMLView unsupportedTextMIMETypes] containsObject:MIMEType])
906                 return NO;
907
908             // If the MIME type is a known plug-in we might not want to load it.
909             if (!allowPlugins && [knownPluginMIMETypes() containsObject:MIMEType]) {
910                 BOOL isSupportedByWebKit = [[WebHTMLView supportedNonImageMIMETypes] containsObject:MIMEType] ||
911                     [[WebHTMLView supportedMIMETypes] containsObject:MIMEType];
912                 
913                 // If this is a known plug-in MIME type and WebKit can't show it natively, we don't want to show it.
914                 if (!isSupportedByWebKit)
915                     return NO;
916             }
917         }
918         if (vClass)
919             *vClass = viewClass;
920         if (rClass)
921             *rClass = repClass;
922         return YES;
923     }
924     
925     return NO;
926 }
927
928 - (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType
929 {
930     if ([[self class] _viewClass:vClass andRepresentationClass:rClass forMIMEType:MIMEType allowingPlugins:[_private->preferences arePlugInsEnabled]])
931         return YES;
932
933     if (_private->pluginDatabase) {
934         WebBasePluginPackage *pluginPackage = [_private->pluginDatabase pluginForMIMEType:MIMEType];
935         if (pluginPackage) {
936             if (vClass)
937                 *vClass = [WebHTMLView class];
938             if (rClass)
939                 *rClass = [WebHTMLRepresentation class];
940             return YES;
941         }
942     }
943     
944     return NO;
945 }
946
947 + (void)_setAlwaysUseATSU:(BOOL)f
948 {
949     [self _setAlwaysUsesComplexTextCodePath:f];
950 }
951
952 + (void)_setAlwaysUsesComplexTextCodePath:(BOOL)f
953 {
954     Font::setCodePath(f ? Font::Complex : Font::Auto);
955 }
956
957 + (BOOL)canCloseAllWebViews
958 {
959     return DOMWindow::dispatchAllPendingBeforeUnloadEvents();
960 }
961
962 + (void)closeAllWebViews
963 {
964     DOMWindow::dispatchAllPendingUnloadEvents();
965
966     // This will close the WebViews in a random order. Change this if close order is important.
967     // Make a new set to avoid mutating the set we are enumerating.
968     NSSet *webViewsToClose = [NSSet setWithSet:(NSSet *)allWebViewsSet]; 
969     NSEnumerator *enumerator = [webViewsToClose objectEnumerator];
970     while (WebView *webView = [enumerator nextObject])
971         [webView close];
972 }
973
974 + (BOOL)canShowFile:(NSString *)path
975 {
976     return [[self class] canShowMIMEType:[WebView _MIMETypeForFile:path]];
977 }
978
979 + (NSString *)suggestedFileExtensionForMIMEType:(NSString *)type
980 {
981     return WKGetPreferredExtensionForMIMEType(type);
982 }
983
984 - (BOOL)_isClosed
985 {
986     return !_private || _private->closed;
987 }
988
989 - (void)_closePluginDatabases
990 {
991     pluginDatabaseClientCount--;
992
993     // Close both sets of plug-in databases because plug-ins need an opportunity to clean up files, etc.
994
995     // Unload the WebView local plug-in database. 
996     if (_private->pluginDatabase) {
997         [_private->pluginDatabase destroyAllPluginInstanceViews];
998         [_private->pluginDatabase close];
999         [_private->pluginDatabase release];
1000         _private->pluginDatabase = nil;
1001     }
1002     
1003     // Keep the global plug-in database active until the app terminates to avoid having to reload plug-in bundles.
1004     if (!pluginDatabaseClientCount && applicationIsTerminating)
1005         [WebPluginDatabase closeSharedDatabase];
1006 }
1007
1008 - (void)_closeWithFastTeardown 
1009 {
1010 #ifndef NDEBUG
1011     WTF::RefCountedLeakCounter::suppressMessages("At least one WebView was closed with fast teardown.");
1012 #endif
1013
1014     [[NSDistributedNotificationCenter defaultCenter] removeObserver:self];
1015     [[NSNotificationCenter defaultCenter] removeObserver:self];
1016
1017     [self _closePluginDatabases];
1018 }
1019
1020 static bool fastDocumentTeardownEnabled()
1021 {
1022 #ifdef NDEBUG
1023     static bool enabled = ![[NSUserDefaults standardUserDefaults] boolForKey:WebKitEnableFullDocumentTeardownPreferenceKey];
1024 #else
1025     static bool initialized = false;
1026     static bool enabled = false;
1027     if (!initialized) {
1028         // This allows debug builds to default to not have fast teardown, so leak checking still works.
1029         // But still allow the WebKitEnableFullDocumentTeardown default to override it if present.
1030         NSNumber *setting = [[NSUserDefaults standardUserDefaults] objectForKey:WebKitEnableFullDocumentTeardownPreferenceKey];
1031         if (setting)
1032             enabled = ![setting boolValue];
1033         initialized = true;
1034     }
1035 #endif
1036     return enabled;
1037 }
1038
1039 // _close is here only for backward compatibility; clients and subclasses should use
1040 // public method -close instead.
1041 - (void)_close
1042 {
1043     if (!_private || _private->closed)
1044         return;
1045
1046     _private->closed = YES;
1047     [self _removeFromAllWebViewsSet];
1048
1049     [self _closingEventHandling];
1050
1051 #ifndef NDEBUG
1052     WTF::RefCountedLeakCounter::cancelMessageSuppression(webViewIsOpen);
1053 #endif
1054
1055     // To quit the apps fast we skip document teardown, except plugins
1056     // need to be destroyed and unloaded.
1057     if (applicationIsTerminating && fastDocumentTeardownEnabled()) {
1058         [self _closeWithFastTeardown];
1059         return;
1060     }
1061
1062 #if ENABLE(VIDEO)
1063     [self _exitFullscreen];
1064 #endif
1065
1066     if (Frame* mainFrame = [self _mainCoreFrame])
1067         mainFrame->loader()->detachFromParent();
1068
1069     [self setHostWindow:nil];
1070
1071     [self setDownloadDelegate:nil];
1072     [self setEditingDelegate:nil];
1073     [self setFrameLoadDelegate:nil];
1074     [self setPolicyDelegate:nil];
1075     [self setResourceLoadDelegate:nil];
1076     [self setScriptDebugDelegate:nil];
1077     [self setUIDelegate:nil];
1078
1079     [_private->inspector webViewClosed];
1080
1081     // To avoid leaks, call removeDragCaret in case it wasn't called after moveDragCaretToPoint.
1082     [self removeDragCaret];
1083
1084     // Deleteing the WebCore::Page will clear the page cache so we call destroy on 
1085     // all the plug-ins in the page cache to break any retain cycles.
1086     // See comment in HistoryItem::releaseAllPendingPageCaches() for more information.
1087     delete _private->page;
1088     _private->page = 0;
1089
1090     if (_private->hasSpellCheckerDocumentTag) {
1091         [[NSSpellChecker sharedSpellChecker] closeSpellDocumentWithTag:_private->spellCheckerDocumentTag];
1092         _private->hasSpellCheckerDocumentTag = NO;
1093     }
1094
1095 #if USE(ACCELERATED_COMPOSITING)
1096     [self _clearLayerSyncLoopObserver];
1097 #endif
1098     
1099     [[NSDistributedNotificationCenter defaultCenter] removeObserver:self];
1100     [[NSNotificationCenter defaultCenter] removeObserver:self];
1101
1102     [WebPreferences _removeReferenceForIdentifier:[self preferencesIdentifier]];
1103
1104     WebPreferences *preferences = _private->preferences;
1105     _private->preferences = nil;
1106     [preferences didRemoveFromWebView];
1107     [preferences release];
1108
1109     [self _closePluginDatabases];
1110
1111 #ifndef NDEBUG
1112     // Need this to make leak messages accurate.
1113     if (applicationIsTerminating) {
1114         gcController().garbageCollectNow();
1115         [WebCache setDisabled:YES];
1116     }
1117 #endif
1118 }
1119
1120 // Indicates if the WebView is in the midst of a user gesture.
1121 - (BOOL)_isProcessingUserGesture
1122 {
1123     WebFrame *frame = [self mainFrame];
1124     return core(frame)->loader()->isProcessingUserGesture();
1125 }
1126
1127 + (NSString *)_MIMETypeForFile:(NSString *)path
1128 {
1129     NSString *extension = [path pathExtension];
1130     NSString *MIMEType = nil;
1131
1132     // Get the MIME type from the extension.
1133     if ([extension length] != 0) {
1134         MIMEType = WKGetMIMETypeForExtension(extension);
1135     }
1136
1137     // If we can't get a known MIME type from the extension, sniff.
1138     if ([MIMEType length] == 0 || [MIMEType isEqualToString:@"application/octet-stream"]) {
1139         NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:path];
1140         NSData *data = [handle readDataOfLength:WEB_GUESS_MIME_TYPE_PEEK_LENGTH];
1141         [handle closeFile];
1142         if ([data length] != 0) {
1143             MIMEType = [data _webkit_guessedMIMEType];
1144         }
1145         if ([MIMEType length] == 0) {
1146             MIMEType = @"application/octet-stream";
1147         }
1148     }
1149
1150     return MIMEType;
1151 }
1152
1153 - (WebDownload *)_downloadURL:(NSURL *)URL
1154 {
1155     ASSERT(URL);
1156     
1157     NSURLRequest *request = [[NSURLRequest alloc] initWithURL:URL];
1158     WebDownload *download = [WebDownload _downloadWithRequest:request
1159                                                      delegate:_private->downloadDelegate
1160                                                     directory:nil];
1161     [request release];
1162     
1163     return download;
1164 }
1165
1166 - (WebView *)_openNewWindowWithRequest:(NSURLRequest *)request
1167 {
1168     NSDictionary *features = [[NSDictionary alloc] init];
1169     WebView *newWindowWebView = [[self _UIDelegateForwarder] webView:self
1170                                             createWebViewWithRequest:nil
1171                                                       windowFeatures:features];
1172     [features release];
1173     if (!newWindowWebView)
1174         return nil;
1175
1176     CallUIDelegate(newWindowWebView, @selector(webViewShow:));
1177     return newWindowWebView;
1178 }
1179
1180 - (WebInspector *)inspector
1181 {
1182     if (!_private->inspector)
1183         _private->inspector = [[WebInspector alloc] initWithWebView:self];
1184     return _private->inspector;
1185 }
1186
1187 - (WebCore::Page*)page
1188 {
1189     return _private->page;
1190 }
1191
1192 - (NSMenu *)_menuForElement:(NSDictionary *)element defaultItems:(NSArray *)items
1193 {
1194     NSArray *defaultMenuItems = [[WebDefaultUIDelegate sharedUIDelegate] webView:self contextMenuItemsForElement:element defaultMenuItems:items];
1195
1196     NSArray *menuItems = CallUIDelegate(self, @selector(webView:contextMenuItemsForElement:defaultMenuItems:), element, defaultMenuItems);
1197     if (!menuItems)
1198         return nil;
1199
1200     unsigned count = [menuItems count];
1201     if (!count)
1202         return nil;
1203
1204     NSMenu *menu = [[NSMenu alloc] init];
1205     for (unsigned i = 0; i < count; i++)
1206         [menu addItem:[menuItems objectAtIndex:i]];
1207
1208     return [menu autorelease];
1209 }
1210
1211 - (void)_mouseDidMoveOverElement:(NSDictionary *)dictionary modifierFlags:(NSUInteger)modifierFlags
1212 {
1213     // We originally intended to call this delegate method sometimes with a nil dictionary, but due to
1214     // a bug dating back to WebKit 1.0 this delegate was never called with nil! Unfortunately we can't
1215     // start calling this with nil since it will break Adobe Help Viewer, and possibly other clients.
1216     if (!dictionary)
1217         return;
1218     CallUIDelegate(self, @selector(webView:mouseDidMoveOverElement:modifierFlags:), dictionary, modifierFlags);
1219 }
1220
1221 - (void)_loadBackForwardListFromOtherView:(WebView *)otherView
1222 {
1223     if (!_private->page)
1224         return;
1225     
1226     if (!otherView->_private->page)
1227         return;
1228     
1229     // It turns out the right combination of behavior is done with the back/forward load
1230     // type.  (See behavior matrix at the top of WebFramePrivate.)  So we copy all the items
1231     // in the back forward list, and go to the current one.
1232
1233     BackForwardList* backForwardList = _private->page->backForwardList();
1234     ASSERT(!backForwardList->currentItem()); // destination list should be empty
1235
1236     BackForwardList* otherBackForwardList = otherView->_private->page->backForwardList();
1237     if (!otherBackForwardList->currentItem())
1238         return; // empty back forward list, bail
1239     
1240     HistoryItem* newItemToGoTo = 0;
1241
1242     int lastItemIndex = otherBackForwardList->forwardListCount();
1243     for (int i = -otherBackForwardList->backListCount(); i <= lastItemIndex; ++i) {
1244         if (i == 0) {
1245             // If this item is showing , save away its current scroll and form state,
1246             // since that might have changed since loading and it is normally not saved
1247             // until we leave that page.
1248             otherView->_private->page->mainFrame()->loader()->history()->saveDocumentAndScrollState();
1249         }
1250         RefPtr<HistoryItem> newItem = otherBackForwardList->itemAtIndex(i)->copy();
1251         if (i == 0) 
1252             newItemToGoTo = newItem.get();
1253         backForwardList->addItem(newItem.release());
1254     }
1255     
1256     ASSERT(newItemToGoTo);
1257     _private->page->goToItem(newItemToGoTo, FrameLoadTypeIndexedBackForward);
1258 }
1259
1260 - (void)_setFormDelegate: (id<WebFormDelegate>)delegate
1261 {
1262     _private->formDelegate = delegate;
1263 }
1264
1265 - (id<WebFormDelegate>)_formDelegate
1266 {
1267     return _private->formDelegate;
1268 }
1269
1270 - (BOOL)_needsAdobeFrameReloadingQuirk
1271 {
1272     static BOOL needsQuirk = WKAppVersionCheckLessThan(@"com.adobe.Acrobat", -1, 9.0)
1273         || WKAppVersionCheckLessThan(@"com.adobe.Acrobat.Pro", -1, 9.0)
1274         || WKAppVersionCheckLessThan(@"com.adobe.Reader", -1, 9.0)
1275         || WKAppVersionCheckLessThan(@"com.adobe.distiller", -1, 9.0)
1276         || WKAppVersionCheckLessThan(@"com.adobe.Contribute", -1, 4.2)
1277         || WKAppVersionCheckLessThan(@"com.adobe.dreamweaver-9.0", -1, 9.1)
1278         || WKAppVersionCheckLessThan(@"com.macromedia.fireworks", -1, 9.1)
1279         || WKAppVersionCheckLessThan(@"com.adobe.InCopy", -1, 5.1)
1280         || WKAppVersionCheckLessThan(@"com.adobe.InDesign", -1, 5.1)
1281         || WKAppVersionCheckLessThan(@"com.adobe.Soundbooth", -1, 2);
1282
1283     return needsQuirk;
1284 }
1285
1286 - (BOOL)_needsLinkElementTextCSSQuirk
1287 {
1288     static BOOL needsQuirk = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_LINK_ELEMENT_TEXT_CSS_QUIRK)
1289         && WKAppVersionCheckLessThan(@"com.e-frontier.shade10", -1, 10.6);
1290     return needsQuirk;
1291 }
1292
1293 - (BOOL)_needsKeyboardEventDisambiguationQuirks
1294 {
1295     static BOOL needsQuirks = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_IE_COMPATIBLE_KEYBOARD_EVENT_DISPATCH) && !applicationIsSafari();
1296     return needsQuirks;
1297 }
1298
1299 - (BOOL)_needsFrameLoadDelegateRetainQuirk
1300 {
1301     static BOOL needsQuirk = WKAppVersionCheckLessThan(@"com.equinux.iSale5", -1, 5.6);    
1302     return needsQuirk;
1303 }
1304
1305 - (void)_preferencesChangedNotification:(NSNotification *)notification
1306 {
1307     WebPreferences *preferences = (WebPreferences *)[notification object];
1308     ASSERT(preferences == [self preferences]);
1309     
1310     if (!_private->userAgentOverridden)
1311         _private->userAgent = String();
1312
1313     // Cache this value so we don't have to read NSUserDefaults on each page load
1314     _private->useSiteSpecificSpoofing = [preferences _useSiteSpecificSpoofing];
1315
1316     // Update corresponding WebCore Settings object.
1317     if (!_private->page)
1318         return;
1319     
1320     Settings* settings = _private->page->settings();
1321     
1322     settings->setCursiveFontFamily([preferences cursiveFontFamily]);
1323     settings->setDefaultFixedFontSize([preferences defaultFixedFontSize]);
1324     settings->setDefaultFontSize([preferences defaultFontSize]);
1325     settings->setDefaultTextEncodingName([preferences defaultTextEncodingName]);
1326     settings->setUsesEncodingDetector([preferences usesEncodingDetector]);
1327     settings->setFantasyFontFamily([preferences fantasyFontFamily]);
1328     settings->setFixedFontFamily([preferences fixedFontFamily]);
1329     settings->setForceFTPDirectoryListings([preferences _forceFTPDirectoryListings]);
1330     settings->setFTPDirectoryTemplatePath([preferences _ftpDirectoryTemplatePath]);
1331     settings->setLocalStorageDatabasePath([preferences _localStorageDatabasePath]);
1332     settings->setJavaEnabled([preferences isJavaEnabled]);
1333     settings->setJavaScriptEnabled([preferences isJavaScriptEnabled]);
1334     settings->setWebSecurityEnabled([preferences isWebSecurityEnabled]);
1335     settings->setAllowUniversalAccessFromFileURLs([preferences allowUniversalAccessFromFileURLs]);
1336     settings->setAllowFileAccessFromFileURLs([preferences allowFileAccessFromFileURLs]);
1337     settings->setJavaScriptCanOpenWindowsAutomatically([preferences javaScriptCanOpenWindowsAutomatically]);
1338     settings->setMinimumFontSize([preferences minimumFontSize]);
1339     settings->setMinimumLogicalFontSize([preferences minimumLogicalFontSize]);
1340     settings->setPluginsEnabled([preferences arePlugInsEnabled]);
1341 #if ENABLE(DATABASE)
1342     Database::setIsAvailable([preferences databasesEnabled]);
1343 #endif
1344     settings->setLocalStorageEnabled([preferences localStorageEnabled]);
1345     settings->setExperimentalNotificationsEnabled([preferences experimentalNotificationsEnabled]);
1346     settings->setPrivateBrowsingEnabled([preferences privateBrowsingEnabled]);
1347     settings->setSansSerifFontFamily([preferences sansSerifFontFamily]);
1348     settings->setSerifFontFamily([preferences serifFontFamily]);
1349     settings->setStandardFontFamily([preferences standardFontFamily]);
1350     settings->setLoadsImagesAutomatically([preferences loadsImagesAutomatically]);
1351     settings->setShouldPrintBackgrounds([preferences shouldPrintBackgrounds]);
1352     settings->setTextAreasAreResizable([preferences textAreasAreResizable]);
1353     settings->setShrinksStandaloneImagesToFit([preferences shrinksStandaloneImagesToFit]);
1354     settings->setEditableLinkBehavior(core([preferences editableLinkBehavior]));
1355     settings->setTextDirectionSubmenuInclusionBehavior(core([preferences textDirectionSubmenuInclusionBehavior]));
1356     settings->setDOMPasteAllowed([preferences isDOMPasteAllowed]);
1357     settings->setUsesPageCache([self usesPageCache]);
1358     settings->setShowsURLsInToolTips([preferences showsURLsInToolTips]);
1359     settings->setDeveloperExtrasEnabled([preferences developerExtrasEnabled]);
1360     settings->setAuthorAndUserStylesEnabled([preferences authorAndUserStylesEnabled]);
1361     settings->setApplicationChromeMode([preferences applicationChromeModeEnabled]);
1362     if ([preferences userStyleSheetEnabled]) {
1363         NSString* location = [[preferences userStyleSheetLocation] _web_originalDataAsString];
1364         if ([location isEqualToString:@"apple-dashboard://stylesheet"])
1365             location = @"file:///System/Library/PrivateFrameworks/DashboardClient.framework/Resources/widget.css";
1366         settings->setUserStyleSheetLocation([NSURL URLWithString:(location ? location : @"")]);
1367     } else
1368         settings->setUserStyleSheetLocation([NSURL URLWithString:@""]);
1369     settings->setNeedsAdobeFrameReloadingQuirk([self _needsAdobeFrameReloadingQuirk]);
1370     settings->setTreatsAnyTextCSSLinkAsStylesheet([self _needsLinkElementTextCSSQuirk]);
1371     settings->setNeedsKeyboardEventDisambiguationQuirks([self _needsKeyboardEventDisambiguationQuirks]);
1372     settings->setNeedsLeopardMailQuirks(runningLeopardMail());
1373     settings->setNeedsTigerMailQuirks(runningTigerMail());
1374     settings->setNeedsSiteSpecificQuirks(_private->useSiteSpecificSpoofing);
1375     settings->setWebArchiveDebugModeEnabled([preferences webArchiveDebugModeEnabled]);
1376     settings->setLocalFileContentSniffingEnabled([preferences localFileContentSniffingEnabled]);
1377     settings->setOfflineWebApplicationCacheEnabled([preferences offlineWebApplicationCacheEnabled]);
1378     settings->setZoomMode([preferences zoomsTextOnly] ? ZoomTextOnly : ZoomPage);
1379     settings->setJavaScriptCanAccessClipboard([preferences javaScriptCanAccessClipboard]);
1380     settings->setXSSAuditorEnabled([preferences isXSSAuditorEnabled]);
1381     settings->setEnforceCSSMIMETypeInStrictMode(!WKAppVersionCheckLessThan(@"com.apple.iWeb", -1, 2.1));
1382     
1383     // FIXME: Enabling accelerated compositing when WebGL is enabled causes tests to fail on Leopard which expect HW compositing to be disabled.
1384     // Until we fix that, I will comment out the test (CFM)
1385     settings->setAcceleratedCompositingEnabled((coreVideoHas7228836Fix() || [preferences webGLEnabled]) && [preferences acceleratedCompositingEnabled]);
1386     settings->setShowDebugBorders([preferences showDebugBorders]);
1387     settings->setShowRepaintCounter([preferences showRepaintCounter]);
1388     settings->setPluginAllowedRunTime([preferences pluginAllowedRunTime]);
1389     settings->setWebGLEnabled([preferences webGLEnabled]);
1390     settings->setLoadDeferringEnabled(shouldEnableLoadDeferring());
1391     settings->setFrameFlatteningEnabled([preferences isFrameFlatteningEnabled]);
1392 }
1393
1394 static inline IMP getMethod(id o, SEL s)
1395 {
1396     return [o respondsToSelector:s] ? [o methodForSelector:s] : 0;
1397 }
1398
1399 - (void)_cacheResourceLoadDelegateImplementations
1400 {
1401     WebResourceDelegateImplementationCache *cache = &_private->resourceLoadDelegateImplementations;
1402     id delegate = _private->resourceProgressDelegate;
1403
1404     if (!delegate) {
1405         bzero(cache, sizeof(WebResourceDelegateImplementationCache));
1406         return;
1407     }
1408
1409     cache->didCancelAuthenticationChallengeFunc = getMethod(delegate, @selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:));
1410     cache->didFailLoadingWithErrorFromDataSourceFunc = getMethod(delegate, @selector(webView:resource:didFailLoadingWithError:fromDataSource:));
1411     cache->didFinishLoadingFromDataSourceFunc = getMethod(delegate, @selector(webView:resource:didFinishLoadingFromDataSource:));
1412     cache->didLoadResourceFromMemoryCacheFunc = getMethod(delegate, @selector(webView:didLoadResourceFromMemoryCache:response:length:fromDataSource:));
1413     cache->didReceiveAuthenticationChallengeFunc = getMethod(delegate, @selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:));
1414 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
1415     cache->canAuthenticateAgainstProtectionSpaceFunc = getMethod(delegate, @selector(webView:resource:canAuthenticateAgainstProtectionSpace:forDataSource:));
1416 #endif
1417     cache->didReceiveContentLengthFunc = getMethod(delegate, @selector(webView:resource:didReceiveContentLength:fromDataSource:));
1418     cache->didReceiveResponseFunc = getMethod(delegate, @selector(webView:resource:didReceiveResponse:fromDataSource:));
1419     cache->identifierForRequestFunc = getMethod(delegate, @selector(webView:identifierForInitialRequest:fromDataSource:));
1420     cache->plugInFailedWithErrorFunc = getMethod(delegate, @selector(webView:plugInFailedWithError:dataSource:));
1421     cache->willCacheResponseFunc = getMethod(delegate, @selector(webView:resource:willCacheResponse:fromDataSource:));
1422     cache->willSendRequestFunc = getMethod(delegate, @selector(webView:resource:willSendRequest:redirectResponse:fromDataSource:));
1423     cache->shouldUseCredentialStorageFunc = getMethod(delegate, @selector(webView:resource:shouldUseCredentialStorageForDataSource:));
1424 }
1425
1426 - (void)_cacheFrameLoadDelegateImplementations
1427 {
1428     WebFrameLoadDelegateImplementationCache *cache = &_private->frameLoadDelegateImplementations;
1429     id delegate = _private->frameLoadDelegate;
1430
1431     if (!delegate) {
1432         bzero(cache, sizeof(WebFrameLoadDelegateImplementationCache));
1433         return;
1434     }
1435
1436     cache->didCancelClientRedirectForFrameFunc = getMethod(delegate, @selector(webView:didCancelClientRedirectForFrame:));
1437     cache->didChangeLocationWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didChangeLocationWithinPageForFrame:));
1438     cache->didPushStateWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didPushStateWithinPageForFrame:));
1439     cache->didReplaceStateWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didReplaceStateWithinPageForFrame:));
1440     cache->didPopStateWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didPopStateWithinPageForFrame:));
1441     cache->didClearWindowObjectForFrameFunc = getMethod(delegate, @selector(webView:didClearWindowObject:forFrame:));
1442     cache->didClearWindowObjectForFrameInScriptWorldFunc = getMethod(delegate, @selector(webView:didClearWindowObjectForFrame:inScriptWorld:));
1443     cache->didClearInspectorWindowObjectForFrameFunc = getMethod(delegate, @selector(webView:didClearInspectorWindowObject:forFrame:));
1444     cache->didCommitLoadForFrameFunc = getMethod(delegate, @selector(webView:didCommitLoadForFrame:));
1445     cache->didFailLoadWithErrorForFrameFunc = getMethod(delegate, @selector(webView:didFailLoadWithError:forFrame:));
1446     cache->didFailProvisionalLoadWithErrorForFrameFunc = getMethod(delegate, @selector(webView:didFailProvisionalLoadWithError:forFrame:));
1447     cache->didFinishDocumentLoadForFrameFunc = getMethod(delegate, @selector(webView:didFinishDocumentLoadForFrame:));
1448     cache->didFinishLoadForFrameFunc = getMethod(delegate, @selector(webView:didFinishLoadForFrame:));
1449     cache->didFirstLayoutInFrameFunc = getMethod(delegate, @selector(webView:didFirstLayoutInFrame:));
1450     cache->didFirstVisuallyNonEmptyLayoutInFrameFunc = getMethod(delegate, @selector(webView:didFirstVisuallyNonEmptyLayoutInFrame:));
1451     cache->didHandleOnloadEventsForFrameFunc = getMethod(delegate, @selector(webView:didHandleOnloadEventsForFrame:));
1452     cache->didReceiveIconForFrameFunc = getMethod(delegate, @selector(webView:didReceiveIcon:forFrame:));
1453     cache->didReceiveServerRedirectForProvisionalLoadForFrameFunc = getMethod(delegate, @selector(webView:didReceiveServerRedirectForProvisionalLoadForFrame:));
1454     cache->didReceiveTitleForFrameFunc = getMethod(delegate, @selector(webView:didReceiveTitle:forFrame:));
1455     cache->didStartProvisionalLoadForFrameFunc = getMethod(delegate, @selector(webView:didStartProvisionalLoadForFrame:));
1456     cache->willCloseFrameFunc = getMethod(delegate, @selector(webView:willCloseFrame:));
1457     cache->willPerformClientRedirectToURLDelayFireDateForFrameFunc = getMethod(delegate, @selector(webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:));
1458     cache->windowScriptObjectAvailableFunc = getMethod(delegate, @selector(webView:windowScriptObjectAvailable:));
1459     cache->didDisplayInsecureContentFunc = getMethod(delegate, @selector(webViewDidDisplayInsecureContent:));
1460     cache->didRunInsecureContentFunc = getMethod(delegate, @selector(webView:didRunInsecureContent:));
1461 }
1462
1463 - (void)_cacheScriptDebugDelegateImplementations
1464 {
1465     WebScriptDebugDelegateImplementationCache *cache = &_private->scriptDebugDelegateImplementations;
1466     id delegate = _private->scriptDebugDelegate;
1467
1468     if (!delegate) {
1469         bzero(cache, sizeof(WebScriptDebugDelegateImplementationCache));
1470         return;
1471     }
1472
1473     cache->didParseSourceFunc = getMethod(delegate, @selector(webView:didParseSource:baseLineNumber:fromURL:sourceId:forWebFrame:));
1474     if (cache->didParseSourceFunc)
1475         cache->didParseSourceExpectsBaseLineNumber = YES;
1476     else
1477         cache->didParseSourceFunc = getMethod(delegate, @selector(webView:didParseSource:fromURL:sourceId:forWebFrame:));
1478
1479     cache->failedToParseSourceFunc = getMethod(delegate, @selector(webView:failedToParseSource:baseLineNumber:fromURL:withError:forWebFrame:));
1480     cache->didEnterCallFrameFunc = getMethod(delegate, @selector(webView:didEnterCallFrame:sourceId:line:forWebFrame:));
1481     cache->willExecuteStatementFunc = getMethod(delegate, @selector(webView:willExecuteStatement:sourceId:line:forWebFrame:));
1482     cache->willLeaveCallFrameFunc = getMethod(delegate, @selector(webView:willLeaveCallFrame:sourceId:line:forWebFrame:));
1483     cache->exceptionWasRaisedFunc = getMethod(delegate, @selector(webView:exceptionWasRaised:sourceId:line:forWebFrame:));
1484 }
1485
1486 - (void)_cacheHistoryDelegateImplementations
1487 {
1488     WebHistoryDelegateImplementationCache *cache = &_private->historyDelegateImplementations;
1489     id delegate = _private->historyDelegate;
1490
1491     if (!delegate) {
1492         bzero(cache, sizeof(WebHistoryDelegateImplementationCache));
1493         return;
1494     }
1495
1496     cache->navigatedFunc = getMethod(delegate, @selector(webView:didNavigateWithNavigationData:inFrame:));
1497     cache->clientRedirectFunc = getMethod(delegate, @selector(webView:didPerformClientRedirectFromURL:toURL:inFrame:));
1498     cache->serverRedirectFunc = getMethod(delegate, @selector(webView:didPerformServerRedirectFromURL:toURL:inFrame:));
1499     cache->setTitleFunc = getMethod(delegate, @selector(webView:updateHistoryTitle:forURL:));
1500     cache->populateVisitedLinksFunc = getMethod(delegate, @selector(populateVisitedLinksForWebView:));
1501 }
1502
1503 - (id)_policyDelegateForwarder
1504 {
1505     if (!_private->policyDelegateForwarder)
1506         _private->policyDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->policyDelegate defaultTarget:[WebDefaultPolicyDelegate sharedPolicyDelegate] catchExceptions:_private->catchesDelegateExceptions];
1507     return _private->policyDelegateForwarder;
1508 }
1509
1510 - (id)_UIDelegateForwarder
1511 {
1512     if (!_private->UIDelegateForwarder)
1513         _private->UIDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->UIDelegate defaultTarget:[WebDefaultUIDelegate sharedUIDelegate] catchExceptions:_private->catchesDelegateExceptions];
1514     return _private->UIDelegateForwarder;
1515 }
1516
1517 - (id)_editingDelegateForwarder
1518 {
1519     // This can be called during window deallocation by QTMovieView in the QuickTime Cocoa Plug-in.
1520     // Not sure if that is a bug or not.
1521     if (!_private)
1522         return nil;
1523
1524     if (!_private->editingDelegateForwarder)
1525         _private->editingDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->editingDelegate defaultTarget:[WebDefaultEditingDelegate sharedEditingDelegate] catchExceptions:_private->catchesDelegateExceptions];
1526     return _private->editingDelegateForwarder;
1527 }
1528
1529 - (void)_closeWindow
1530 {
1531     [[self _UIDelegateForwarder] webViewClose:self];
1532 }
1533
1534 + (void)_unregisterViewClassAndRepresentationClassForMIMEType:(NSString *)MIMEType
1535 {
1536     [[WebFrameView _viewTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType];
1537     [[WebDataSource _repTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType];
1538     
1539     // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
1540     // in the WebCore MIMEType registry.  For now we're doing this in a safe, limited manner
1541     // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
1542     MIMETypeRegistry::getSupportedNonImageMIMETypes().remove(MIMEType);
1543 }
1544
1545 + (void)_registerViewClass:(Class)viewClass representationClass:(Class)representationClass forURLScheme:(NSString *)URLScheme
1546 {
1547     NSString *MIMEType = [self _generatedMIMETypeForURLScheme:URLScheme];
1548     [self registerViewClass:viewClass representationClass:representationClass forMIMEType:MIMEType];
1549
1550     // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
1551     // in the WebCore MIMEType registry.  For now we're doing this in a safe, limited manner
1552     // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
1553     if ([viewClass class] == [WebHTMLView class])
1554         MIMETypeRegistry::getSupportedNonImageMIMETypes().add(MIMEType);
1555     
1556     // This is used to make _representationExistsForURLScheme faster.
1557     // Without this set, we'd have to create the MIME type each time.
1558     if (schemesWithRepresentationsSet == nil) {
1559         schemesWithRepresentationsSet = [[NSMutableSet alloc] init];
1560     }
1561     [schemesWithRepresentationsSet addObject:[[[URLScheme lowercaseString] copy] autorelease]];
1562 }
1563
1564 + (NSString *)_generatedMIMETypeForURLScheme:(NSString *)URLScheme
1565 {
1566     return [@"x-apple-web-kit/" stringByAppendingString:[URLScheme lowercaseString]];
1567 }
1568
1569 + (BOOL)_representationExistsForURLScheme:(NSString *)URLScheme
1570 {
1571     return [schemesWithRepresentationsSet containsObject:[URLScheme lowercaseString]];
1572 }
1573
1574 + (BOOL)_canHandleRequest:(NSURLRequest *)request forMainFrame:(BOOL)forMainFrame
1575 {
1576     // FIXME: If <rdar://problem/5217309> gets fixed, this check can be removed.
1577     if (!request)
1578         return NO;
1579
1580     if ([NSURLConnection canHandleRequest:request])
1581         return YES;
1582
1583     NSString *scheme = [[request URL] scheme];
1584
1585     // Representations for URL schemes work at the top level.
1586     if (forMainFrame && [self _representationExistsForURLScheme:scheme])
1587         return YES;
1588         
1589     return [scheme _webkit_isCaseInsensitiveEqualToString:@"applewebdata"];
1590 }
1591
1592 + (BOOL)_canHandleRequest:(NSURLRequest *)request
1593 {
1594     return [self _canHandleRequest:request forMainFrame:YES];
1595 }
1596
1597 + (NSString *)_decodeData:(NSData *)data
1598 {
1599     HTMLNames::init(); // this method is used for importing bookmarks at startup, so HTMLNames are likely to be uninitialized yet
1600     RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("text/html"); // bookmark files are HTML
1601     String result = decoder->decode(static_cast<const char*>([data bytes]), [data length]);
1602     result += decoder->flush();
1603     return result;
1604 }
1605
1606 - (void)_pushPerformingProgrammaticFocus
1607 {
1608     _private->programmaticFocusCount++;
1609 }
1610
1611 - (void)_popPerformingProgrammaticFocus
1612 {
1613     _private->programmaticFocusCount--;
1614 }
1615
1616 - (BOOL)_isPerformingProgrammaticFocus
1617 {
1618     return _private->programmaticFocusCount != 0;
1619 }
1620
1621 - (void)_didChangeValueForKey: (NSString *)key
1622 {
1623     LOG (Bindings, "calling didChangeValueForKey: %@", key);
1624     [self didChangeValueForKey: key];
1625 }
1626
1627 - (void)_willChangeValueForKey: (NSString *)key
1628 {
1629     LOG (Bindings, "calling willChangeValueForKey: %@", key);
1630     [self willChangeValueForKey: key];
1631 }
1632
1633 + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key {
1634     static NSSet *manualNotifyKeys = nil;
1635     if (!manualNotifyKeys)
1636         manualNotifyKeys = [[NSSet alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey,
1637             _WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, _WebMainFrameDocumentKey,
1638             nil];
1639     if ([manualNotifyKeys containsObject:key])
1640         return NO;
1641     return YES;
1642 }
1643
1644 - (NSArray *)_declaredKeys {
1645     static NSArray *declaredKeys = nil;
1646     if (!declaredKeys)
1647         declaredKeys = [[NSArray alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey,
1648             _WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, _WebMainFrameDocumentKey, nil];
1649     return declaredKeys;
1650 }
1651
1652 - (void)setObservationInfo:(void *)info
1653 {
1654     _private->observationInfo = info;
1655 }
1656
1657 - (void *)observationInfo
1658 {
1659     return _private->observationInfo;
1660 }
1661
1662 - (void)_willChangeBackForwardKeys
1663 {
1664     [self _willChangeValueForKey: _WebCanGoBackKey];
1665     [self _willChangeValueForKey: _WebCanGoForwardKey];
1666 }
1667
1668 - (void)_didChangeBackForwardKeys
1669 {
1670     [self _didChangeValueForKey: _WebCanGoBackKey];
1671     [self _didChangeValueForKey: _WebCanGoForwardKey];
1672 }
1673
1674 - (void)_didStartProvisionalLoadForFrame:(WebFrame *)frame
1675 {
1676     [self _willChangeBackForwardKeys];
1677     if (frame == [self mainFrame]){
1678         // Force an observer update by sending a will/did.
1679         [self _willChangeValueForKey: _WebIsLoadingKey];
1680         [self _didChangeValueForKey: _WebIsLoadingKey];
1681
1682         [self _willChangeValueForKey: _WebMainFrameURLKey];
1683     }
1684
1685     [NSApp setWindowsNeedUpdate:YES];
1686 }
1687
1688 - (void)_didCommitLoadForFrame:(WebFrame *)frame
1689 {
1690     if (frame == [self mainFrame])
1691         [self _didChangeValueForKey: _WebMainFrameURLKey];
1692     [NSApp setWindowsNeedUpdate:YES];
1693 }
1694
1695 - (void)_didFinishLoadForFrame:(WebFrame *)frame
1696 {
1697     [self _didChangeBackForwardKeys];
1698     if (frame == [self mainFrame]){
1699         // Force an observer update by sending a will/did.
1700         [self _willChangeValueForKey: _WebIsLoadingKey];
1701         [self _didChangeValueForKey: _WebIsLoadingKey];
1702     }
1703     [NSApp setWindowsNeedUpdate:YES];
1704 }
1705
1706 - (void)_didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
1707 {
1708     [self _didChangeBackForwardKeys];
1709     if (frame == [self mainFrame]){
1710         // Force an observer update by sending a will/did.
1711         [self _willChangeValueForKey: _WebIsLoadingKey];
1712         [self _didChangeValueForKey: _WebIsLoadingKey];
1713     }
1714     [NSApp setWindowsNeedUpdate:YES];
1715 }
1716
1717 - (void)_didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
1718 {
1719     [self _didChangeBackForwardKeys];
1720     if (frame == [self mainFrame]){
1721         // Force an observer update by sending a will/did.
1722         [self _willChangeValueForKey: _WebIsLoadingKey];
1723         [self _didChangeValueForKey: _WebIsLoadingKey];
1724         
1725         [self _didChangeValueForKey: _WebMainFrameURLKey];
1726     }
1727     [NSApp setWindowsNeedUpdate:YES];
1728 }
1729
1730 - (NSCachedURLResponse *)_cachedResponseForURL:(NSURL *)URL
1731 {
1732     NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:URL];
1733     [request _web_setHTTPUserAgent:[self userAgentForURL:URL]];
1734     NSCachedURLResponse *cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:request];
1735     [request release];
1736     return cachedResponse;
1737 }
1738
1739 - (void)_writeImageForElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
1740 {
1741     NSURL *linkURL = [element objectForKey:WebElementLinkURLKey];
1742     DOMElement *domElement = [element objectForKey:WebElementDOMNodeKey];
1743     [pasteboard _web_writeImage:(NSImage *)(domElement ? nil : [element objectForKey:WebElementImageKey])
1744                         element:domElement
1745                             URL:linkURL ? linkURL : (NSURL *)[element objectForKey:WebElementImageURLKey]
1746                           title:[element objectForKey:WebElementImageAltStringKey] 
1747                         archive:[[element objectForKey:WebElementDOMNodeKey] webArchive]
1748                           types:types
1749                          source:nil];
1750 }
1751
1752 - (void)_writeLinkElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
1753 {
1754     [pasteboard _web_writeURL:[element objectForKey:WebElementLinkURLKey]
1755                      andTitle:[element objectForKey:WebElementLinkLabelKey]
1756                         types:types];
1757 }
1758
1759 - (void)_setInitiatedDrag:(BOOL)initiatedDrag
1760 {
1761     if (!_private->page)
1762         return;
1763     _private->page->dragController()->setDidInitiateDrag(initiatedDrag);
1764 }
1765
1766 #if ENABLE(DASHBOARD_SUPPORT)
1767
1768 #define DASHBOARD_CONTROL_LABEL @"control"
1769
1770 - (void)_addControlRect:(NSRect)bounds clip:(NSRect)clip fromView:(NSView *)view toDashboardRegions:(NSMutableDictionary *)regions
1771 {
1772     NSRect adjustedBounds = bounds;
1773     adjustedBounds.origin = [self convertPoint:bounds.origin fromView:view];
1774     adjustedBounds.origin.y = [self bounds].size.height - adjustedBounds.origin.y;
1775     adjustedBounds.size = bounds.size;
1776
1777     NSRect adjustedClip;
1778     adjustedClip.origin = [self convertPoint:clip.origin fromView:view];
1779     adjustedClip.origin.y = [self bounds].size.height - adjustedClip.origin.y;
1780     adjustedClip.size = clip.size;
1781
1782     WebDashboardRegion *region = [[WebDashboardRegion alloc] initWithRect:adjustedBounds 
1783         clip:adjustedClip type:WebDashboardRegionTypeScrollerRectangle];
1784     NSMutableArray *scrollerRegions = [regions objectForKey:DASHBOARD_CONTROL_LABEL];
1785     if (!scrollerRegions) {
1786         scrollerRegions = [[NSMutableArray alloc] init];
1787         [regions setObject:scrollerRegions forKey:DASHBOARD_CONTROL_LABEL];
1788         [scrollerRegions release];
1789     }
1790     [scrollerRegions addObject:region];
1791     [region release];
1792 }
1793
1794 - (void)_addScrollerDashboardRegionsForFrameView:(FrameView*)frameView dashboardRegions:(NSMutableDictionary *)regions
1795 {    
1796     NSView *documentView = [[kit(frameView->frame()) frameView] documentView];
1797
1798     const HashSet<RefPtr<Widget> >* children = frameView->children();
1799     HashSet<RefPtr<Widget> >::const_iterator end = children->end();
1800     for (HashSet<RefPtr<Widget> >::const_iterator it = children->begin(); it != end; ++it) {
1801         Widget* widget = (*it).get();
1802         if (widget->isFrameView()) {
1803             [self _addScrollerDashboardRegionsForFrameView:static_cast<FrameView*>(widget) dashboardRegions:regions];
1804             continue;
1805         }
1806
1807         if (!widget->isScrollbar())
1808             continue;
1809
1810         // FIXME: This should really pass an appropriate clip, but our first try got it wrong, and
1811         // it's not common to need this to be correct in Dashboard widgets.
1812         NSRect bounds = widget->frameRect();
1813         [self _addControlRect:bounds clip:bounds fromView:documentView toDashboardRegions:regions];
1814     }
1815 }
1816
1817 - (void)_addScrollerDashboardRegions:(NSMutableDictionary *)regions from:(NSArray *)views
1818 {
1819     // Add scroller regions for NSScroller and WebCore scrollbars
1820     NSUInteger count = [views count];
1821     for (NSUInteger i = 0; i < count; i++) {
1822         NSView *view = [views objectAtIndex:i];
1823         
1824         if ([view isKindOfClass:[WebHTMLView class]]) {
1825             if (Frame* coreFrame = core([(WebHTMLView*)view _frame])) {
1826                 if (FrameView* coreView = coreFrame->view())
1827                     [self _addScrollerDashboardRegionsForFrameView:coreView dashboardRegions:regions];
1828             }
1829         } else if ([view isKindOfClass:[NSScroller class]]) {
1830             // AppKit places absent scrollers at -100,-100
1831             if ([view frame].origin.y < 0)
1832                 continue;
1833             [self _addControlRect:[view bounds] clip:[view visibleRect] fromView:view toDashboardRegions:regions];
1834         }
1835         [self _addScrollerDashboardRegions:regions from:[view subviews]];
1836     }
1837 }
1838
1839 - (void)_addScrollerDashboardRegions:(NSMutableDictionary *)regions
1840 {
1841     [self _addScrollerDashboardRegions:regions from:[self subviews]];
1842 }
1843
1844 - (NSDictionary *)_dashboardRegions
1845 {
1846     // Only return regions from main frame.
1847     Frame* mainFrame = [self _mainCoreFrame];
1848     if (!mainFrame)
1849         return nil;
1850     NSMutableDictionary *regions = mainFrame->dashboardRegionsDictionary();
1851     [self _addScrollerDashboardRegions:regions];
1852     return regions;
1853 }
1854
1855 - (void)_setDashboardBehavior:(WebDashboardBehavior)behavior to:(BOOL)flag
1856 {
1857     // FIXME: Remove this blanket assignment once Dashboard and Dashcode implement 
1858     // specific support for the backward compatibility mode flag.
1859     if (behavior == WebDashboardBehaviorAllowWheelScrolling && flag == NO && _private->page)
1860         _private->page->settings()->setUsesDashboardBackwardCompatibilityMode(true);
1861     
1862     switch (behavior) {
1863         case WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows: {
1864             _private->dashboardBehaviorAlwaysSendMouseEventsToAllWindows = flag;
1865             break;
1866         }
1867         case WebDashboardBehaviorAlwaysSendActiveNullEventsToPlugIns: {
1868             _private->dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns = flag;
1869             break;
1870         }
1871         case WebDashboardBehaviorAlwaysAcceptsFirstMouse: {
1872             _private->dashboardBehaviorAlwaysAcceptsFirstMouse = flag;
1873             break;
1874         }
1875         case WebDashboardBehaviorAllowWheelScrolling: {
1876             _private->dashboardBehaviorAllowWheelScrolling = flag;
1877             break;
1878         }
1879         case WebDashboardBehaviorUseBackwardCompatibilityMode: {
1880             if (_private->page)
1881                 _private->page->settings()->setUsesDashboardBackwardCompatibilityMode(flag);
1882             break;
1883         }
1884     }
1885 }
1886
1887 - (BOOL)_dashboardBehavior:(WebDashboardBehavior)behavior
1888 {
1889     switch (behavior) {
1890         case WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows: {
1891             return _private->dashboardBehaviorAlwaysSendMouseEventsToAllWindows;
1892         }
1893         case WebDashboardBehaviorAlwaysSendActiveNullEventsToPlugIns: {
1894             return _private->dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns;
1895         }
1896         case WebDashboardBehaviorAlwaysAcceptsFirstMouse: {
1897             return _private->dashboardBehaviorAlwaysAcceptsFirstMouse;
1898         }
1899         case WebDashboardBehaviorAllowWheelScrolling: {
1900             return _private->dashboardBehaviorAllowWheelScrolling;
1901         }
1902         case WebDashboardBehaviorUseBackwardCompatibilityMode: {
1903             return _private->page && _private->page->settings()->usesDashboardBackwardCompatibilityMode();
1904         }
1905     }
1906     return NO;
1907 }
1908
1909 #endif /* ENABLE(DASHBOARD_SUPPORT) */
1910
1911 + (void)_setShouldUseFontSmoothing:(BOOL)f
1912 {
1913     Font::setShouldUseSmoothing(f);
1914 }
1915
1916 + (BOOL)_shouldUseFontSmoothing
1917 {
1918     return Font::shouldUseSmoothing();
1919 }
1920
1921 + (void)_setUsesTestModeFocusRingColor:(BOOL)f
1922 {
1923     setUsesTestModeFocusRingColor(f);
1924 }
1925
1926 + (BOOL)_usesTestModeFocusRingColor
1927 {
1928     return usesTestModeFocusRingColor();
1929 }
1930
1931 - (void)setAlwaysShowVerticalScroller:(BOOL)flag
1932 {
1933     WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
1934     if (flag) {
1935         [scrollview setVerticalScrollingMode:ScrollbarAlwaysOn andLock:YES];
1936     } else {
1937         [scrollview setVerticalScrollingModeLocked:NO];
1938         [scrollview setVerticalScrollingMode:ScrollbarAuto andLock:NO];
1939     }
1940 }
1941
1942 - (BOOL)alwaysShowVerticalScroller
1943 {
1944     WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
1945     return [scrollview verticalScrollingModeLocked] && [scrollview verticalScrollingMode] == ScrollbarAlwaysOn;
1946 }
1947
1948 - (void)setAlwaysShowHorizontalScroller:(BOOL)flag
1949 {
1950     WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
1951     if (flag) {
1952         [scrollview setHorizontalScrollingMode:ScrollbarAlwaysOn andLock:YES];
1953     } else {
1954         [scrollview setHorizontalScrollingModeLocked:NO];
1955         [scrollview setHorizontalScrollingMode:ScrollbarAuto andLock:NO];
1956     }
1957 }
1958
1959 - (void)setProhibitsMainFrameScrolling:(BOOL)prohibits
1960 {
1961     if (Frame* mainFrame = [self _mainCoreFrame])
1962         mainFrame->view()->setProhibitsScrolling(prohibits);
1963 }
1964
1965 - (BOOL)alwaysShowHorizontalScroller
1966 {
1967     WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
1968     return [scrollview horizontalScrollingModeLocked] && [scrollview horizontalScrollingMode] == ScrollbarAlwaysOn;
1969 }
1970
1971 - (void)_setInViewSourceMode:(BOOL)flag
1972 {
1973     if (Frame* mainFrame = [self _mainCoreFrame])
1974         mainFrame->setInViewSourceMode(flag);
1975 }
1976
1977 - (BOOL)_inViewSourceMode
1978 {
1979     Frame* mainFrame = [self _mainCoreFrame];
1980     return mainFrame && mainFrame->inViewSourceMode();
1981 }
1982
1983 - (void)_setUseFastImageScalingMode:(BOOL)flag
1984 {
1985     if (_private->page && _private->page->inLowQualityImageInterpolationMode() != flag) {
1986         _private->page->setInLowQualityImageInterpolationMode(flag);
1987         [self setNeedsDisplay:YES];
1988     }
1989 }
1990
1991 - (BOOL)_inFastImageScalingMode
1992 {
1993     if (_private->page)
1994         return _private->page->inLowQualityImageInterpolationMode();
1995     return NO;
1996 }
1997
1998 - (BOOL)_cookieEnabled
1999 {
2000     if (_private->page)
2001         return _private->page->cookieEnabled();
2002     return YES;
2003 }
2004
2005 - (void)_setCookieEnabled:(BOOL)enable
2006 {
2007     if (_private->page)
2008         _private->page->setCookieEnabled(enable);
2009 }
2010
2011 - (void)_setAdditionalWebPlugInPaths:(NSArray *)newPaths
2012 {
2013     if (!_private->pluginDatabase)
2014         _private->pluginDatabase = [[WebPluginDatabase alloc] init];
2015         
2016     [_private->pluginDatabase setPlugInPaths:newPaths];
2017     [_private->pluginDatabase refresh];
2018 }
2019
2020 - (void)_attachScriptDebuggerToAllFrames
2021 {
2022     for (Frame* frame = [self _mainCoreFrame]; frame; frame = frame->tree()->traverseNext())
2023         [kit(frame) _attachScriptDebugger];
2024 }
2025
2026 - (void)_detachScriptDebuggerFromAllFrames
2027 {
2028     for (Frame* frame = [self _mainCoreFrame]; frame; frame = frame->tree()->traverseNext())
2029         [kit(frame) _detachScriptDebugger];
2030 }
2031
2032 - (void)setBackgroundColor:(NSColor *)backgroundColor
2033 {
2034     if ([_private->backgroundColor isEqual:backgroundColor])
2035         return;
2036
2037     id old = _private->backgroundColor;
2038     _private->backgroundColor = [backgroundColor retain];
2039     [old release];
2040
2041     [[self mainFrame] _updateBackgroundAndUpdatesWhileOffscreen];
2042 }
2043
2044 - (NSColor *)backgroundColor
2045 {
2046     return _private->backgroundColor;
2047 }
2048
2049 - (BOOL)defersCallbacks
2050 {
2051     if (!_private->page)
2052         return NO;
2053     return _private->page->defersLoading();
2054 }
2055
2056 - (void)setDefersCallbacks:(BOOL)defer
2057 {
2058     if (!_private->page)
2059         return;
2060     return _private->page->setDefersLoading(defer);
2061 }
2062
2063 // For backwards compatibility with the WebBackForwardList API, we honor both
2064 // a per-WebView and a per-preferences setting for whether to use the page cache.
2065
2066 - (BOOL)usesPageCache
2067 {
2068     return _private->usesPageCache && [[self preferences] usesPageCache];
2069 }
2070
2071 - (void)setUsesPageCache:(BOOL)usesPageCache
2072 {
2073     _private->usesPageCache = usesPageCache;
2074
2075     // Post a notification so the WebCore settings update.
2076     [[self preferences] _postPreferencesChangesNotification];
2077 }
2078
2079 - (WebHistoryItem *)_globalHistoryItem
2080 {
2081     if (!_private->page)
2082         return nil;
2083     return kit(_private->page->globalHistoryItem());
2084 }
2085
2086 - (WebTextIterator *)textIteratorForRect:(NSRect)rect
2087 {
2088     IntPoint rectStart(rect.origin.x, rect.origin.y);
2089     IntPoint rectEnd(rect.origin.x + rect.size.width, rect.origin.y + rect.size.height);
2090     
2091     Frame* coreFrame = [self _mainCoreFrame];
2092     if (!coreFrame)
2093         return nil;
2094     
2095     VisibleSelection selectionInsideRect(coreFrame->visiblePositionForPoint(rectStart), coreFrame->visiblePositionForPoint(rectEnd));
2096     
2097     return [[[WebTextIterator alloc] initWithRange:kit(selectionInsideRect.toNormalizedRange().get())] autorelease];
2098 }
2099
2100 - (void)handleAuthenticationForResource:(id)identifier challenge:(NSURLAuthenticationChallenge *)challenge fromDataSource:(WebDataSource *)dataSource 
2101 {
2102     NSWindow *window = [self hostWindow] ? [self hostWindow] : [self window]; 
2103     [[WebPanelAuthenticationHandler sharedHandler] startAuthentication:challenge window:window]; 
2104
2105
2106 - (void)_clearUndoRedoOperations
2107 {
2108     if (!_private->page)
2109         return;
2110     _private->page->clearUndoRedoOperations();
2111 }
2112
2113 - (void)_setCatchesDelegateExceptions:(BOOL)f
2114 {
2115     _private->catchesDelegateExceptions = f;
2116 }
2117
2118 - (BOOL)_catchesDelegateExceptions
2119 {
2120     return _private->catchesDelegateExceptions;
2121 }
2122
2123 - (void)_executeCoreCommandByName:(NSString *)name value:(NSString *)value
2124 {
2125     Frame* coreFrame = [self _mainCoreFrame];
2126     if (!coreFrame)
2127         return;
2128     coreFrame->editor()->command(name).execute(value);
2129 }
2130
2131 - (void)_setCustomHTMLTokenizerTimeDelay:(double)timeDelay
2132 {
2133     if (!_private->page)
2134         return;
2135     return _private->page->setCustomHTMLTokenizerTimeDelay(timeDelay);
2136 }
2137
2138 - (void)_setCustomHTMLTokenizerChunkSize:(int)chunkSize
2139 {
2140     if (!_private->page)
2141         return;
2142     return _private->page->setCustomHTMLTokenizerChunkSize(chunkSize);
2143 }
2144
2145 - (void)_clearMainFrameName
2146 {
2147     _private->page->mainFrame()->tree()->clearName();
2148 }
2149
2150 - (void)setSelectTrailingWhitespaceEnabled:(BOOL)flag
2151 {
2152     _private->selectTrailingWhitespaceEnabled = flag;
2153     if (flag)
2154         [self setSmartInsertDeleteEnabled:false];
2155 }
2156
2157 - (BOOL)isSelectTrailingWhitespaceEnabled
2158 {
2159     return _private->selectTrailingWhitespaceEnabled;
2160 }
2161
2162 - (void)setMemoryCacheDelegateCallsEnabled:(BOOL)enabled
2163 {
2164     _private->page->setMemoryCacheClientCallsEnabled(enabled);
2165 }
2166
2167 - (BOOL)areMemoryCacheDelegateCallsEnabled
2168 {
2169     return _private->page->areMemoryCacheClientCallsEnabled();
2170 }
2171
2172 - (void)_setJavaScriptURLsAreAllowed:(BOOL)areAllowed
2173 {
2174     _private->page->setJavaScriptURLsAreAllowed(areAllowed);
2175 }
2176
2177 + (NSCursor *)_pointingHandCursor
2178 {
2179     return handCursor().impl();
2180 }
2181
2182 - (BOOL)_postsAcceleratedCompositingNotifications
2183 {
2184 #if USE(ACCELERATED_COMPOSITING)
2185     return _private->postsAcceleratedCompositingNotifications;
2186 #else
2187     return NO;
2188 #endif
2189
2190 }
2191 - (void)_setPostsAcceleratedCompositingNotifications:(BOOL)flag
2192 {
2193 #if USE(ACCELERATED_COMPOSITING)
2194     _private->postsAcceleratedCompositingNotifications = flag;
2195 #endif
2196 }
2197
2198 - (BOOL)_isUsingAcceleratedCompositing
2199 {
2200 #if USE(ACCELERATED_COMPOSITING)
2201     if (_private->usesDocumentViews) {
2202         Frame* coreFrame = [self _mainCoreFrame];
2203         for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
2204             NSView *documentView = [[kit(frame) frameView] documentView];
2205             if ([documentView isKindOfClass:[WebHTMLView class]] && [(WebHTMLView *)documentView _isUsingAcceleratedCompositing])
2206                 return YES;
2207         }
2208     }
2209 #endif
2210     return NO;
2211 }
2212
2213 - (BOOL)_isSoftwareRenderable
2214 {
2215 #if USE(ACCELERATED_COMPOSITING)
2216     if (_private->usesDocumentViews) {
2217         Frame* coreFrame = [self _mainCoreFrame];
2218         for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
2219             if (FrameView* view = frame->view()) {
2220                 if (!view->isSoftwareRenderable())
2221                     return NO;
2222             }
2223         }
2224     }
2225 #endif
2226     return YES;
2227 }
2228
2229 - (void)_setIncludesFlattenedCompositingLayersWhenDrawingToBitmap:(BOOL)flag
2230 {
2231     _private->includesFlattenedCompositingLayersWhenDrawingToBitmap = flag;
2232 }
2233
2234 - (BOOL)_includesFlattenedCompositingLayersWhenDrawingToBitmap
2235 {
2236     return _private->includesFlattenedCompositingLayersWhenDrawingToBitmap;
2237 }
2238
2239 static WebBaseNetscapePluginView *_pluginViewForNode(DOMNode *node)
2240 {
2241     if (!node)
2242         return nil;
2243     
2244     Node* coreNode = core(node);
2245     if (!coreNode)
2246         return nil;
2247     
2248     RenderObject* renderer = coreNode->renderer();
2249     if (!renderer || !renderer->isWidget())
2250         return nil;
2251     
2252     Widget* widget = toRenderWidget(renderer)->widget();
2253     if (!widget || !widget->platformWidget())
2254         return nil;
2255     
2256     NSView *view = widget->platformWidget();
2257     if (![view isKindOfClass:[WebBaseNetscapePluginView class]])
2258         return nil;
2259     
2260     return (WebBaseNetscapePluginView *)view;
2261 }
2262
2263 + (BOOL)_isNodeHaltedPlugin:(DOMNode *)node
2264 {
2265     return [_pluginViewForNode(node) isHalted];
2266 }
2267
2268 + (BOOL)_hasPluginForNodeBeenHalted:(DOMNode *)node
2269 {
2270     return [_pluginViewForNode(node) hasBeenHalted];
2271 }
2272 + (void)_restartHaltedPluginForNode:(DOMNode *)node
2273 {
2274     if (!node)
2275         return;
2276     
2277     [_pluginViewForNode(node) resumeFromHalt];
2278 }
2279
2280 - (NSPasteboard *)_insertionPasteboard
2281 {
2282     return _private ? _private->insertionPasteboard : nil;
2283 }
2284
2285 + (void)_addOriginAccessWhitelistEntryWithSourceOrigin:(NSString *)sourceOrigin destinationProtocol:(NSString *)destinationProtocol destinationHost:(NSString *)destinationHost allowDestinationSubdomains:(BOOL)allowDestinationSubdomains
2286 {
2287     SecurityOrigin::addOriginAccessWhitelistEntry(*SecurityOrigin::createFromString(sourceOrigin), destinationProtocol, destinationHost, allowDestinationSubdomains);
2288 }
2289
2290 + (void)_removeOriginAccessWhitelistEntryWithSourceOrigin:(NSString *)sourceOrigin destinationProtocol:(NSString *)destinationProtocol destinationHost:(NSString *)destinationHost allowDestinationSubdomains:(BOOL)allowDestinationSubdomains
2291 {
2292     SecurityOrigin::removeOriginAccessWhitelistEntry(*SecurityOrigin::createFromString(sourceOrigin), destinationProtocol, destinationHost, allowDestinationSubdomains);
2293 }
2294
2295 +(void)_resetOriginAccessWhitelists
2296 {
2297     SecurityOrigin::resetOriginAccessWhitelists();
2298 }
2299
2300 - (void)_updateActiveState
2301 {
2302     if (_private && _private->page)
2303         _private->page->focusController()->setActive([[self window] isKeyWindow]);
2304 }
2305
2306 static PassOwnPtr<Vector<String> > toStringVector(NSArray* patterns)
2307 {
2308     // Convert the patterns into Vectors.
2309     NSUInteger count = [patterns count];
2310     if (count == 0)
2311         return 0;
2312     Vector<String>* patternsVector = new Vector<String>;
2313     for (NSUInteger i = 0; i < count; ++i) {
2314         id entry = [patterns objectAtIndex:i];
2315         if ([entry isKindOfClass:[NSString class]])
2316             patternsVector->append(String((NSString*)entry));
2317     }
2318     return patternsVector;
2319 }
2320
2321 + (void)_addUserScriptToGroup:(NSString *)groupName world:(WebScriptWorld *)world source:(NSString *)source url:(NSURL *)url
2322                     whitelist:(NSArray *)whitelist blacklist:(NSArray *)blacklist injectionTime:(WebUserScriptInjectionTime)injectionTime
2323 {
2324     String group(groupName);
2325     if (group.isEmpty())
2326         return;
2327     
2328     PageGroup* pageGroup = PageGroup::pageGroup(group);
2329     if (!pageGroup)
2330         return;
2331     
2332     pageGroup->addUserScriptToWorld(core(world), source, url, toStringVector(whitelist), toStringVector(blacklist), 
2333                                     injectionTime == WebInjectAtDocumentStart ? InjectAtDocumentStart : InjectAtDocumentEnd);
2334 }
2335
2336 + (void)_addUserStyleSheetToGroup:(NSString *)groupName world:(WebScriptWorld *)world source:(NSString *)source url:(NSURL *)url
2337                         whitelist:(NSArray *)whitelist blacklist:(NSArray *)blacklist
2338 {
2339     String group(groupName);
2340     if (group.isEmpty())
2341         return;
2342     
2343     PageGroup* pageGroup = PageGroup::pageGroup(group);
2344     if (!pageGroup)
2345         return;
2346
2347     pageGroup->addUserStyleSheetToWorld(core(world), source, url, toStringVector(whitelist), toStringVector(blacklist));
2348 }
2349
2350 + (void)_removeUserScriptFromGroup:(NSString *)groupName world:(WebScriptWorld *)world url:(NSURL *)url
2351 {
2352     String group(groupName);
2353     if (group.isEmpty())
2354         return;
2355     
2356     PageGroup* pageGroup = PageGroup::pageGroup(group);
2357     if (!pageGroup)
2358         return;
2359
2360     pageGroup->removeUserScriptFromWorld(core(world), url);
2361 }
2362
2363 + (void)_removeUserStyleSheetFromGroup:(NSString *)groupName world:(WebScriptWorld *)world url:(NSURL *)url
2364 {
2365     String group(groupName);
2366     if (group.isEmpty())
2367         return;
2368     
2369     PageGroup* pageGroup = PageGroup::pageGroup(group);
2370     if (!pageGroup)
2371         return;
2372
2373     pageGroup->removeUserStyleSheetFromWorld(core(world), url);
2374 }
2375
2376 + (void)_removeUserScriptsFromGroup:(NSString *)groupName world:(WebScriptWorld *)world
2377 {
2378     String group(groupName);
2379     if (group.isEmpty())
2380         return;
2381     
2382     PageGroup* pageGroup = PageGroup::pageGroup(group);
2383     if (!pageGroup)
2384         return;
2385
2386     pageGroup->removeUserScriptsFromWorld(core(world));
2387 }
2388
2389 + (void)_removeUserStyleSheetsFromGroup:(NSString *)groupName world:(WebScriptWorld *)world
2390 {
2391     String group(groupName);
2392     if (group.isEmpty())
2393         return;
2394     
2395     PageGroup* pageGroup = PageGroup::pageGroup(group);
2396     if (!pageGroup)
2397         return;
2398
2399     pageGroup->removeUserStyleSheetsFromWorld(core(world));
2400 }
2401
2402 + (void)_removeAllUserContentFromGroup:(NSString *)groupName
2403 {
2404     String group(groupName);
2405     if (group.isEmpty())
2406         return;
2407     
2408     PageGroup* pageGroup = PageGroup::pageGroup(group);
2409     if (!pageGroup)
2410         return;
2411     
2412     pageGroup->removeAllUserContent();
2413 }
2414
2415 - (BOOL)cssAnimationsSuspended
2416 {
2417     return _private->cssAnimationsSuspended;
2418 }
2419
2420 - (void)setCSSAnimationsSuspended:(BOOL)suspended
2421 {
2422     if (suspended == _private->cssAnimationsSuspended)
2423         return;
2424         
2425     _private->cssAnimationsSuspended = suspended;
2426     
2427     Frame* frame = core([self mainFrame]);
2428     if (suspended)
2429         frame->animation()->suspendAnimations(frame->document());
2430     else
2431         frame->animation()->resumeAnimations(frame->document());
2432 }
2433
2434 + (void)_setDomainRelaxationForbidden:(BOOL)forbidden forURLScheme:(NSString *)scheme
2435 {
2436     SecurityOrigin::setDomainRelaxationForbiddenForURLScheme(forbidden, scheme);
2437 }
2438
2439 + (void)_registerURLSchemeAsSecure:(NSString *)scheme
2440 {
2441     SecurityOrigin::registerURLSchemeAsSecure(scheme);
2442 }
2443
2444 @end
2445
2446 @implementation _WebSafeForwarder
2447
2448 // Used to send messages to delegates that implement informal protocols.
2449
2450 - (id)initWithTarget:(id)t defaultTarget:(id)dt catchExceptions:(BOOL)c
2451 {
2452     self = [super init];
2453     if (!self)
2454         return nil;
2455     target = t; // Non retained.
2456     defaultTarget = dt;
2457     catchExceptions = c;
2458     return self;
2459 }
2460
2461 - (void)forwardInvocation:(NSInvocation *)invocation
2462 {
2463     if ([target respondsToSelector:[invocation selector]]) {
2464         if (catchExceptions) {
2465             @try {
2466                 [invocation invokeWithTarget:target];
2467             } @catch(id exception) {
2468                 ReportDiscardedDelegateException([invocation selector], exception);
2469             }
2470         } else
2471             [invocation invokeWithTarget:target];
2472         return;
2473     }
2474
2475     if ([defaultTarget respondsToSelector:[invocation selector]])
2476         [invocation invokeWithTarget:defaultTarget];
2477
2478     // Do nothing quietly if method not implemented.
2479 }
2480
2481 - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
2482 {
2483     return [defaultTarget methodSignatureForSelector:aSelector];
2484 }
2485
2486 @end
2487
2488 @implementation WebView
2489
2490 + (void)initialize
2491 {
2492     static BOOL initialized = NO;
2493     if (initialized)
2494         return;
2495     initialized = YES;
2496
2497     InitWebCoreSystemInterface();
2498     JSC::initializeThreading();
2499     WTF::initializeMainThreadToProcessMainThread();
2500
2501     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_applicationWillTerminate) name:NSApplicationWillTerminateNotification object:NSApp];
2502     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:) name:WebPreferencesChangedNotification object:nil];
2503     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesRemovedNotification:) name:WebPreferencesRemovedNotification object:nil];    
2504
2505     continuousSpellCheckingEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebContinuousSpellCheckingEnabled];
2506 #ifndef BUILDING_ON_TIGER
2507     grammarCheckingEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebGrammarCheckingEnabled];
2508 #endif
2509
2510 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
2511     automaticQuoteSubstitutionEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticQuoteSubstitutionEnabled];
2512     automaticLinkDetectionEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticLinkDetectionEnabled];
2513     automaticDashSubstitutionEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticDashSubstitutionEnabled];
2514     automaticTextReplacementEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticTextReplacementEnabled];
2515     automaticSpellingCorrectionEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticSpellingCorrectionEnabled];
2516 #endif
2517 }
2518
2519 + (void)_applicationWillTerminate
2520 {   
2521     applicationIsTerminating = YES;
2522
2523     if (fastDocumentTeardownEnabled())
2524         [self closeAllWebViews];
2525
2526     if (!pluginDatabaseClientCount)
2527         [WebPluginDatabase closeSharedDatabase];
2528
2529     PageGroup::closeLocalStorage();
2530 }
2531
2532 + (BOOL)_canShowMIMEType:(NSString *)MIMEType allowingPlugins:(BOOL)allowPlugins
2533 {
2534     return [self _viewClass:nil andRepresentationClass:nil forMIMEType:MIMEType allowingPlugins:allowPlugins];
2535 }
2536
2537 + (BOOL)canShowMIMEType:(NSString *)MIMEType
2538 {
2539     return [self _canShowMIMEType:MIMEType allowingPlugins:YES];
2540 }
2541
2542 - (BOOL)_canShowMIMEType:(NSString *)MIMEType
2543 {
2544     return [[self class] _canShowMIMEType:MIMEType allowingPlugins:[_private->preferences arePlugInsEnabled]];
2545 }
2546
2547 - (WebBasePluginPackage *)_pluginForMIMEType:(NSString *)MIMEType
2548 {
2549     if (![_private->preferences arePlugInsEnabled])
2550         return nil;
2551
2552     WebBasePluginPackage *pluginPackage = [[WebPluginDatabase sharedDatabase] pluginForMIMEType:MIMEType];
2553     if (pluginPackage)
2554         return pluginPackage;
2555     
2556     if (_private->pluginDatabase)
2557         return [_private->pluginDatabase pluginForMIMEType:MIMEType];
2558     
2559     return nil;
2560 }
2561
2562 - (WebBasePluginPackage *)_pluginForExtension:(NSString *)extension
2563 {
2564     if (![_private->preferences arePlugInsEnabled])
2565         return nil;
2566
2567     WebBasePluginPackage *pluginPackage = [[WebPluginDatabase sharedDatabase] pluginForExtension:extension];
2568     if (pluginPackage)
2569         return pluginPackage;
2570     
2571     if (_private->pluginDatabase)
2572         return [_private->pluginDatabase pluginForExtension:extension];
2573     
2574     return nil;
2575 }
2576
2577 - (void)addPluginInstanceView:(NSView *)view
2578 {
2579     if (!_private->pluginDatabase)
2580         _private->pluginDatabase = [[WebPluginDatabase alloc] init];
2581     [_private->pluginDatabase addPluginInstanceView:view];
2582 }
2583
2584 - (void)removePluginInstanceView:(NSView *)view
2585 {
2586     if (_private->pluginDatabase)
2587         [_private->pluginDatabase removePluginInstanceView:view];    
2588 }
2589
2590 - (void)removePluginInstanceViewsFor:(WebFrame*)webFrame 
2591 {
2592     if (_private->pluginDatabase)
2593         [_private->pluginDatabase removePluginInstanceViewsFor:webFrame];    
2594 }
2595
2596 - (BOOL)_isMIMETypeRegisteredAsPlugin:(NSString *)MIMEType
2597 {
2598     if (![_private->preferences arePlugInsEnabled])
2599         return NO;
2600
2601     if ([[WebPluginDatabase sharedDatabase] isMIMETypeRegistered:MIMEType])
2602         return YES;
2603         
2604     if (_private->pluginDatabase && [_private->pluginDatabase isMIMETypeRegistered:MIMEType])
2605         return YES;
2606     
2607     return NO;
2608 }
2609
2610 + (BOOL)canShowMIMETypeAsHTML:(NSString *)MIMEType
2611 {
2612     return [WebFrameView _canShowMIMETypeAsHTML:MIMEType];
2613 }
2614
2615 + (NSArray *)MIMETypesShownAsHTML
2616 {
2617     NSMutableDictionary *viewTypes = [WebFrameView _viewTypesAllowImageTypeOmission:YES];
2618     NSEnumerator *enumerator = [viewTypes keyEnumerator];
2619     id key;
2620     NSMutableArray *array = [[[NSMutableArray alloc] init] autorelease];
2621     
2622     while ((key = [enumerator nextObject])) {
2623         if ([viewTypes objectForKey:key] == [WebHTMLView class])
2624             [array addObject:key];
2625     }
2626     
2627     return array;
2628 }
2629
2630 + (void)setMIMETypesShownAsHTML:(NSArray *)MIMETypes
2631 {
2632     NSDictionary *viewTypes = [[WebFrameView _viewTypesAllowImageTypeOmission:YES] copy];
2633     NSEnumerator *enumerator = [viewTypes keyEnumerator];
2634     id key;
2635     while ((key = [enumerator nextObject])) {
2636         if ([viewTypes objectForKey:key] == [WebHTMLView class])
2637             [WebView _unregisterViewClassAndRepresentationClassForMIMEType:key];
2638     }
2639     
2640     int i, count = [MIMETypes count];
2641     for (i = 0; i < count; i++) {
2642         [WebView registerViewClass:[WebHTMLView class] 
2643                 representationClass:[WebHTMLRepresentation class] 
2644                 forMIMEType:[MIMETypes objectAtIndex:i]];
2645     }
2646     [viewTypes release];
2647 }
2648
2649 + (NSURL *)URLFromPasteboard:(NSPasteboard *)pasteboard
2650 {
2651     return [pasteboard _web_bestURL];
2652 }
2653
2654 + (NSString *)URLTitleFromPasteboard:(NSPasteboard *)pasteboard
2655 {
2656     return [pasteboard stringForType:WebURLNamePboardType];
2657 }
2658
2659 + (void)registerURLSchemeAsLocal:(NSString *)protocol
2660 {
2661     SecurityOrigin::registerURLSchemeAsLocal(protocol);
2662 }
2663
2664 - (id)_initWithArguments:(NSDictionary *) arguments
2665 {
2666     NSCoder *decoder = [arguments objectForKey:@"decoder"];
2667     if (decoder) {
2668         self = [self initWithCoder:decoder];
2669     } else {
2670         ASSERT([arguments objectForKey:@"frame"]);
2671         NSValue *frameValue = [arguments objectForKey:@"frame"];
2672         NSRect frame = (frameValue ? [frameValue rectValue] : NSZeroRect);
2673         NSString *frameName = [arguments objectForKey:@"frameName"];
2674         NSString *groupName = [arguments objectForKey:@"groupName"];
2675         self = [self initWithFrame:frame frameName:frameName groupName:groupName];
2676     }
2677
2678     return self;
2679 }
2680
2681 static bool clientNeedsWebViewInitThreadWorkaround()
2682 {
2683     if (WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_WEBVIEW_INIT_THREAD_WORKAROUND))
2684         return false;
2685
2686     NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
2687
2688     // Installer.
2689     if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.installer"])
2690         return true;
2691
2692     // Automator.
2693     if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.Automator"])
2694         return true;
2695
2696     // Automator Runner.
2697     if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.AutomatorRunner"])
2698         return true;
2699
2700     // Automator workflows.
2701     if ([bundleIdentifier _webkit_hasCaseInsensitivePrefix:@"com.apple.Automator."])
2702         return true;
2703
2704 #if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
2705     // Mail.
2706     if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.Mail"])
2707         return true;
2708 #endif
2709
2710     return false;
2711 }
2712
2713 static bool needsWebViewInitThreadWorkaround()
2714 {
2715     static bool isOldClient = clientNeedsWebViewInitThreadWorkaround();
2716     return isOldClient && !pthread_main_np();
2717 }
2718
2719 - (id)initWithFrame:(NSRect)f
2720 {
2721     return [self initWithFrame:f frameName:nil groupName:nil];
2722 }
2723
2724 - (id)initWithFrame:(NSRect)f frameName:(NSString *)frameName groupName:(NSString *)groupName
2725 {
2726     if (needsWebViewInitThreadWorkaround())
2727         return [[self _webkit_invokeOnMainThread] initWithFrame:f frameName:frameName groupName:groupName];
2728
2729     WebCoreThreadViolationCheckRoundTwo();
2730     return [self _initWithFrame:f frameName:frameName groupName:groupName usesDocumentViews:YES];
2731 }
2732
2733 - (id)initWithCoder:(NSCoder *)decoder
2734 {
2735     if (needsWebViewInitThreadWorkaround())
2736         return [[self _webkit_invokeOnMainThread] initWithCoder:decoder];
2737
2738     WebCoreThreadViolationCheckRoundTwo();
2739     WebView *result = nil;
2740
2741     @try {
2742         NSString *frameName;
2743         NSString *groupName;
2744         WebPreferences *preferences;
2745         BOOL useBackForwardList = NO;
2746         BOOL allowsUndo = YES;
2747         
2748         result = [super initWithCoder:decoder];
2749         result->_private = [[WebViewPrivate alloc] init];
2750
2751         // We don't want any of the archived subviews. The subviews will always
2752         // be created in _commonInitializationFrameName:groupName:.
2753         [[result subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
2754
2755         if ([decoder allowsKeyedCoding]) {
2756             frameName = [decoder decodeObjectForKey:@"FrameName"];
2757             groupName = [decoder decodeObjectForKey:@"GroupName"];
2758             preferences = [decoder decodeObjectForKey:@"Preferences"];
2759             useBackForwardList = [decoder decodeBoolForKey:@"UseBackForwardList"];
2760             if ([decoder containsValueForKey:@"AllowsUndo"])
2761                 allowsUndo = [decoder decodeBoolForKey:@"AllowsUndo"];
2762         } else {
2763             int version;
2764             [decoder decodeValueOfObjCType:@encode(int) at:&version];
2765             frameName = [decoder decodeObject];
2766             groupName = [decoder decodeObject];
2767             preferences = [decoder decodeObject];
2768             if (version > 1)
2769                 [decoder decodeValuesOfObjCTypes:"c", &useBackForwardList];
2770             // The allowsUndo field is no longer written out in encodeWithCoder, but since there are
2771             // version 3 NIBs that have this field encoded, we still need to read it in.
2772             if (version == 3)
2773                 [decoder decodeValuesOfObjCTypes:"c", &allowsUndo];
2774         }
2775
2776         if (![frameName isKindOfClass:[NSString class]])
2777             frameName = nil;
2778         if (![groupName isKindOfClass:[NSString class]])
2779             groupName = nil;
2780         if (![preferences isKindOfClass:[WebPreferences class]])
2781             preferences = nil;
2782
2783         LOG(Encoding, "FrameName = %@, GroupName = %@, useBackForwardList = %d\n", frameName, groupName, (int)useBackForwardList);
2784         [result _commonInitializationWithFrameName:frameName groupName:groupName usesDocumentViews:YES];
2785         [result page]->backForwardList()->setEnabled(useBackForwardList);
2786         result->_private->allowsUndo = allowsUndo;
2787         if (preferences)
2788             [result setPreferences:preferences];
2789     } @catch (NSException *localException) {
2790         result = nil;
2791         [self release];
2792     }
2793
2794     return result;
2795 }
2796
2797 - (void)encodeWithCoder:(NSCoder *)encoder
2798 {
2799     // Set asside the subviews before we archive. We don't want to archive any subviews.
2800     // The subviews will always be created in _commonInitializationFrameName:groupName:.
2801     id originalSubviews = _subviews;
2802     _subviews = nil;
2803
2804     [super encodeWithCoder:encoder];
2805
2806     // Restore the subviews we set aside.
2807     _subviews = originalSubviews;
2808
2809     BOOL useBackForwardList = _private->page && _private->page->backForwardList()->enabled();
2810     if ([encoder allowsKeyedCoding]) {
2811         [encoder encodeObject:[[self mainFrame] name] forKey:@"FrameName"];
2812         [encoder encodeObject:[self groupName] forKey:@"GroupName"];
2813         [encoder encodeObject:[self preferences] forKey:@"Preferences"];
2814         [encoder encodeBool:useBackForwardList forKey:@"UseBackForwardList"];
2815         [encoder encodeBool:_private->allowsUndo forKey:@"AllowsUndo"];
2816     } else {
2817         int version = WebViewVersion;
2818         [encoder encodeValueOfObjCType:@encode(int) at:&version];
2819         [encoder encodeObject:[[self mainFrame] name]];
2820         [encoder encodeObject:[self groupName]];
2821         [encoder encodeObject:[self preferences]];
2822         [encoder encodeValuesOfObjCTypes:"c", &useBackForwardList];
2823         // DO NOT encode any new fields here, doing so will break older WebKit releases.
2824     }
2825
2826     LOG(Encoding, "FrameName = %@, GroupName = %@, useBackForwardList = %d\n", [[self mainFrame] name], [self groupName], (int)useBackForwardList);
2827 }
2828
2829 - (void)dealloc
2830 {
2831     if (WebCoreObjCScheduleDeallocateOnMainThread([WebView class], self))
2832         return;
2833
2834     // call close to ensure we tear-down completely
2835     // this maintains our old behavior for existing applications
2836     [self close];
2837
2838     if ([[self class] shouldIncludeInWebKitStatistics])
2839         --WebViewCount;
2840
2841     if ([self _needsFrameLoadDelegateRetainQuirk])
2842         [_private->frameLoadDelegate release];
2843         
2844     [_private release];
2845     // [super dealloc] can end up dispatching against _private (3466082)
2846     _private = nil;
2847
2848     [super dealloc];
2849 }
2850
2851 - (void)finalize
2852 {
2853     ASSERT(_private->closed);
2854
2855     --WebViewCount;
2856
2857     [super finalize];
2858 }
2859
2860 - (void)close
2861 {
2862     // _close existed first, and some clients might be calling or overriding it, so call through.
2863     [self _close];
2864 }
2865
2866 - (void)setShouldCloseWithWindow:(BOOL)close
2867 {
2868     _private->shouldCloseWithWindow = close;
2869 }
2870
2871 - (BOOL)shouldCloseWithWindow
2872 {
2873     return _private->shouldCloseWithWindow;
2874 }
2875
2876 - (void)addWindowObserversForWindow:(NSWindow *)window
2877 {
2878     if (window) {
2879         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowDidBecomeKey:)
2880             name:NSWindowDidBecomeKeyNotification object:nil];
2881         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowDidResignKey:)
2882             name:NSWindowDidResignKeyNotification object:nil];
2883         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillOrderOnScreen:)
2884             name:WKWindowWillOrderOnScreenNotification() object:window];
2885     }
2886 }
2887
2888 - (void)removeWindowObservers
2889 {
2890     NSWindow *window = [self window];
2891     if (window) {
2892         [[NSNotificationCenter defaultCenter] removeObserver:self
2893             name:NSWindowDidBecomeKeyNotification object:nil];
2894         [[NSNotificationCenter defaultCenter] removeObserver:self
2895             name:NSWindowDidResignKeyNotification object:nil];
2896         [[NSNotificationCenter defaultCenter] removeObserver:self
2897             name:WKWindowWillOrderOnScreenNotification() object:window];
2898     }
2899 }
2900
2901 - (void)viewWillMoveToWindow:(NSWindow *)window
2902 {
2903     // Don't do anything if the WebView isn't initialized.
2904     // This happens when decoding a WebView in a nib.
2905     // FIXME: What sets up the observer of NSWindowWillCloseNotification in this case?
2906     if (!_private || _private->closed)
2907         return;
2908     
2909     if ([self window] && [self window] != [self hostWindow])
2910         [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowWillCloseNotification object:[self window]];
2911
2912     if (window) {
2913         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillClose:) name:NSWindowWillCloseNotification object:window];
2914          
2915         // Ensure that we will receive the events that WebHTMLView (at least) needs.
2916         // The following are expensive enough that we don't want to call them over
2917         // and over, so do them when we move into a window.
2918         [window setAcceptsMouseMovedEvents:YES];
2919         WKSetNSWindowShouldPostEventNotifications(window, YES);
2920     } else {
2921         _private->page->setCanStartMedia(false);
2922         _private->page->willMoveOffscreen();
2923     }
2924         
2925     if (window != [self window]) {
2926         [self removeWindowObservers];
2927         [self addWindowObserversForWindow:window];
2928     }
2929 }
2930
2931 - (void)viewDidMoveToWindow
2932 {
2933     // Don't do anything if we aren't initialized.  This happens
2934     // when decoding a WebView.  When WebViews are decoded their subviews
2935     // are created by initWithCoder: and so won't be normally
2936     // initialized.  The stub views are discarded by WebView.
2937     if (!_private || _private->closed)
2938         return;
2939
2940     if ([self window]) {
2941         _private->page->setCanStartMedia(true);
2942         _private->page->didMoveOnscreen();
2943     }
2944     
2945     [self _updateActiveState];
2946 }
2947
2948 - (void)_windowDidBecomeKey:(NSNotification *)notification
2949 {
2950     NSWindow *keyWindow = [notification object];
2951     if (keyWindow == [self window] || keyWindow == [[self window] attachedSheet])
2952         [self _updateActiveState];
2953 }
2954
2955 - (void)_windowDidResignKey:(NSNotification *)notification
2956 {
2957     NSWindow *formerKeyWindow = [notification object];
2958     if (formerKeyWindow == [self window] || formerKeyWindow == [[self window] attachedSheet])
2959         [self _updateActiveState];
2960 }
2961
2962 - (void)_windowWillOrderOnScreen:(NSNotification *)notification
2963 {
2964     if (![self shouldUpdateWhileOffscreen])
2965         [self setNeedsDisplay:YES];
2966 }
2967
2968 - (void)_windowWillClose:(NSNotification *)notification
2969 {
2970     if ([self shouldCloseWithWindow] && ([self window] == [self hostWindow] || ([self window] && ![self hostWindow]) || (![self window] && [self hostWindow])))
2971         [self close];
2972 }
2973
2974 - (void)setPreferences:(WebPreferences *)prefs
2975 {
2976     if (!prefs)
2977         prefs = [WebPreferences standardPreferences];
2978
2979     if (_private->preferences == prefs)
2980         return;
2981
2982     [prefs willAddToWebView];
2983
2984     WebPreferences *oldPrefs = _private->preferences;
2985
2986     [[NSNotificationCenter defaultCenter] removeObserver:self name:WebPreferencesChangedNotification object:[self preferences]];
2987     [WebPreferences _removeReferenceForIdentifier:[oldPrefs identifier]];
2988
2989     _private->preferences = [prefs retain];
2990
2991     // After registering for the notification, post it so the WebCore settings update.
2992     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:)
2993         name:WebPreferencesChangedNotification object:[self preferences]];
2994     [[self preferences] _postPreferencesChangesNotification];
2995
2996     [oldPrefs didRemoveFromWebView];
2997     [oldPrefs release];
2998 }
2999
3000 - (WebPreferences *)preferences
3001 {
3002     return _private->preferences;
3003 }
3004
3005 - (void)setPreferencesIdentifier:(NSString *)anIdentifier
3006 {
3007     if (!_private->closed && ![anIdentifier isEqual:[[self preferences] identifier]]) {
3008         WebPreferences *prefs = [[WebPreferences alloc] initWithIdentifier:anIdentifier];
3009         [self setPreferences:prefs];
3010         [prefs release];
3011     }
3012 }
3013
3014 - (NSString *)preferencesIdentifier
3015 {
3016     return [[self preferences] identifier];
3017 }
3018
3019
3020 - (void)setUIDelegate:delegate
3021 {
3022     _private->UIDelegate = delegate;
3023     [_private->UIDelegateForwarder release];
3024     _private->UIDelegateForwarder = nil;
3025 }
3026
3027 - UIDelegate
3028 {
3029     return _private->UIDelegate;
3030 }
3031
3032 - (void)setResourceLoadDelegate: delegate
3033 {
3034     _private->resourceProgressDelegate = delegate;
3035     [self _cacheResourceLoadDelegateImplementations];
3036 }
3037
3038 - resourceLoadDelegate
3039 {
3040     return _private->resourceProgressDelegate;
3041 }
3042
3043 - (void)setDownloadDelegate: delegate
3044 {
3045     _private->downloadDelegate = delegate;
3046 }
3047
3048
3049 - downloadDelegate
3050 {
3051     return _private->downloadDelegate;
3052 }
3053
3054 - (void)setPolicyDelegate:delegate
3055 {
3056     _private->policyDelegate = delegate;
3057     [_private->policyDelegateForwarder release];
3058     _private->policyDelegateForwarder = nil;
3059 }
3060
3061 - policyDelegate
3062 {
3063     return _private->policyDelegate;
3064 }
3065
3066 - (void)setFrameLoadDelegate:delegate
3067 {
3068     // <rdar://problem/6950660> - Due to some subtle WebKit changes - presumably to delegate callback behavior - we've
3069     // unconvered a latent bug in at least one WebKit app where the delegate wasn't properly retained by the app and
3070     // was dealloc'ed before being cleared.
3071     // This is an effort to keep such apps working for now.
3072     if ([self _needsFrameLoadDelegateRetainQuirk]) {
3073         [delegate retain];
3074         [_private->frameLoadDelegate release];
3075     }
3076     
3077     _private->frameLoadDelegate = delegate;
3078     [self _cacheFrameLoadDelegateImplementations];
3079
3080 #if ENABLE(ICONDATABASE)
3081     // If this delegate wants callbacks for icons, fire up the icon database.
3082     if (_private->frameLoadDelegateImplementations.didReceiveIconForFrameFunc)
3083         [WebIconDatabase sharedIconDatabase];
3084 #endif
3085 }
3086
3087 - frameLoadDelegate
3088 {
3089     return _private->frameLoadDelegate;
3090 }
3091
3092 - (WebFrame *)mainFrame
3093 {
3094     // This can be called in initialization, before _private has been set up (3465613)
3095     if (!_private || !_private->page)
3096         return nil;
3097     return kit(_private->page->mainFrame());
3098 }
3099
3100 - (WebFrame *)selectedFrame
3101 {
3102     if (_private->usesDocumentViews) {
3103         // If the first responder is a view in our tree, we get the frame containing the first responder.
3104         // This is faster than searching the frame hierarchy, and will give us a result even in the case
3105         // where the focused frame doesn't actually contain a selection.
3106         WebFrame *focusedFrame = [self _focusedFrame];
3107         if (focusedFrame)
3108             return focusedFrame;
3109     }
3110     
3111     // If the first responder is outside of our view tree, we search for a frame containing a selection.
3112     // There should be at most only one of these.
3113     return [[self mainFrame] _findFrameWithSelection];
3114 }
3115
3116 - (WebBackForwardList *)backForwardList
3117 {
3118     if (!_private->page)
3119         return nil;
3120     if (!_private->page->backForwardList()->enabled())
3121         return nil;
3122     return kit(_private->page->backForwardList());
3123 }
3124
3125 - (void)setMaintainsBackForwardList:(BOOL)flag
3126 {
3127     if (!_private->page)
3128         return;
3129     _private->page->backForwardList()->setEnabled(flag);
3130 }
3131
3132 - (BOOL)goBack
3133 {
3134     if (!_private->page)
3135         return NO;
3136     
3137     return _private->page->goBack();
3138 }
3139
3140 - (BOOL)goForward
3141 {
3142     if (!_private->page)
3143         return NO;
3144
3145     return _private->page->goForward();
3146 }
3147
3148 - (BOOL)goToBackForwardItem:(WebHistoryItem *)item
3149 {
3150     if (!_private->page)
3151         return NO;
3152
3153     _private->page->goToItem(core(item), FrameLoadTypeIndexedBackForward);
3154     return YES;
3155 }
3156
3157 - (void)setTextSizeMultiplier:(float)m
3158 {
3159     [self _setZoomMultiplier:m isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3160 }
3161
3162 - (float)textSizeMultiplier
3163 {
3164     return [self _realZoomMultiplierIsTextOnly] ? _private->zoomMultiplier : 1.0f;
3165 }
3166
3167 - (void)_setZoomMultiplier:(float)m isTextOnly:(BOOL)isTextOnly
3168 {
3169     // NOTE: This has no visible effect when viewing a PDF (see <rdar://problem/4737380>)
3170     _private->zoomMultiplier = m;
3171     ASSERT(_private->page);
3172     if (_private->page)
3173         _private->page->settings()->setZoomMode(isTextOnly ? ZoomTextOnly : ZoomPage);
3174     
3175     // FIXME: it would be nice to rework this code so that _private->zoomMultiplier doesn't exist and callers
3176     // all access _private->page->settings().
3177     Frame* coreFrame = [self _mainCoreFrame];
3178     if (coreFrame)
3179         coreFrame->setZoomFactor(m, isTextOnly ? ZoomTextOnly : ZoomPage);
3180 }
3181
3182 - (float)_zoomMultiplier:(BOOL)isTextOnly
3183 {
3184     if (isTextOnly != [self _realZoomMultiplierIsTextOnly])
3185         return 1.0f;
3186     return _private->zoomMultiplier;
3187 }
3188
3189 - (float)_realZoomMultiplier
3190 {
3191     return _private->zoomMultiplier;
3192 }
3193
3194 - (BOOL)_realZoomMultiplierIsTextOnly
3195 {
3196     if (!_private->page)
3197         return NO;
3198     
3199     return _private->page->settings()->zoomMode() == ZoomTextOnly;
3200 }
3201
3202 #define MinimumZoomMultiplier       0.5f
3203 #define MaximumZoomMultiplier       3.0f
3204 #define ZoomMultiplierRatio         1.2f
3205
3206 - (BOOL)_canZoomOut:(BOOL)isTextOnly
3207 {
3208     id docView = [[[self mainFrame] frameView] documentView];
3209     if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
3210         id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
3211         return [zoomingDocView _canZoomOut];
3212     }
3213     return [self _zoomMultiplier:isTextOnly] / ZoomMultiplierRatio > MinimumZoomMultiplier;
3214 }
3215
3216
3217 - (BOOL)_canZoomIn:(BOOL)isTextOnly
3218 {
3219     id docView = [[[self mainFrame] frameView] documentView];
3220     if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
3221         id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
3222         return [zoomingDocView _canZoomIn];
3223     }
3224     return [self _zoomMultiplier:isTextOnly] * ZoomMultiplierRatio < MaximumZoomMultiplier;
3225 }
3226
3227 - (IBAction)_zoomOut:(id)sender isTextOnly:(BOOL)isTextOnly
3228 {
3229     id docView = [[[self mainFrame] frameView] documentView];
3230     if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
3231         id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
3232         return [zoomingDocView _zoomOut:sender];
3233     }
3234     float newScale = [self _zoomMultiplier:isTextOnly] / ZoomMultiplierRatio;
3235     if (newScale > MinimumZoomMultiplier)
3236         [self _setZoomMultiplier:newScale isTextOnly:isTextOnly];
3237 }
3238
3239 - (IBAction)_zoomIn:(id)sender isTextOnly:(BOOL)isTextOnly
3240 {
3241     id docView = [[[self mainFrame] frameView] documentView];
3242     if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
3243         id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
3244         return [zoomingDocView _zoomIn:sender];
3245     }
3246     float newScale = [self _zoomMultiplier:isTextOnly] * ZoomMultiplierRatio;
3247     if (newScale < MaximumZoomMultiplier)
3248         [self _setZoomMultiplier:newScale isTextOnly:isTextOnly];
3249 }
3250
3251 - (BOOL)_canResetZoom:(BOOL)isTextOnly
3252 {
3253     id docView = [[[self mainFrame] frameView] documentView];
3254     if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
3255         id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
3256         return [zoomingDocView _canResetZoom];
3257     }
3258     return [self _zoomMultiplier:isTextOnly] != 1.0f;
3259 }
3260
3261 - (IBAction)_resetZoom:(id)sender isTextOnly:(BOOL)isTextOnly
3262 {
3263     id docView = [[[self mainFrame] frameView] documentView];
3264     if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
3265         id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
3266         return [zoomingDocView _resetZoom:sender];
3267     }
3268     if ([self _zoomMultiplier:isTextOnly] != 1.0f)
3269         [self _setZoomMultiplier:1.0f isTextOnly:isTextOnly];
3270 }
3271
3272 - (void)setApplicationNameForUserAgent:(NSString *)applicationName
3273 {
3274     NSString *name = [applicationName copy];
3275     [_private->applicationNameForUserAgent release];
3276     _private->applicationNameForUserAgent = name;
3277     if (!_private->userAgentOverridden)
3278         _private->userAgent = String();
3279 }
3280
3281 - (NSString *)applicationNameForUserAgent
3282 {
3283     return [[_private->applicationNameForUserAgent retain] autorelease];
3284 }
3285
3286 - (void)setCustomUserAgent:(NSString *)userAgentString
3287 {
3288     _private->userAgent = userAgentString;
3289     _private->userAgentOverridden = userAgentString != nil;
3290 }
3291
3292 - (NSString *)customUserAgent
3293 {
3294     if (!_private->userAgentOverridden)
3295         return nil;
3296     return _private->userAgent;
3297 }
3298
3299 - (void)setMediaStyle:(NSString *)mediaStyle
3300 {
3301     if (_private->mediaStyle != mediaStyle) {
3302         [_private->mediaStyle release];
3303         _private->mediaStyle = [mediaStyle copy];
3304     }
3305 }
3306
3307 - (NSString *)mediaStyle
3308 {
3309     return _private->mediaStyle;
3310 }
3311
3312 - (BOOL)supportsTextEncoding
3313 {
3314     id documentView = [[[self mainFrame] frameView] documentView];
3315     return [documentView conformsToProtocol:@protocol(WebDocumentText)]
3316         && [documentView supportsTextEncoding];
3317 }
3318
3319 - (void)setCustomTextEncodingName:(NSString *)encoding
3320 {
3321     NSString *oldEncoding = [self customTextEncodingName];
3322     if (encoding == oldEncoding || [encoding isEqualToString:oldEncoding])
3323         return;
3324     if (Frame* mainFrame = [self _mainCoreFrame])
3325         mainFrame->loader()->reloadWithOverrideEncoding(encoding);
3326 }
3327
3328 - (NSString *)_mainFrameOverrideEncoding
3329 {
3330     WebDataSource *dataSource = [[self mainFrame] provisionalDataSource];
3331     if (dataSource == nil)
3332         dataSource = [[self mainFrame] _dataSource];
3333     if (dataSource == nil)
3334         return nil;
3335     return nsStringNilIfEmpty([dataSource _documentLoader]->overrideEncoding());
3336 }
3337
3338 - (NSString *)customTextEncodingName
3339 {
3340     return [self _mainFrameOverrideEncoding];
3341 }
3342
3343 - (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script
3344 {
3345     // Return statements are only valid in a function but some applications pass in scripts
3346     // prefixed with return (<rdar://problems/5103720&4616860>) since older WebKit versions
3347     // silently ignored the return. If the application is linked against an earlier version
3348     // of WebKit we will strip the return so the script wont fail.
3349     if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_JAVASCRIPT_RETURN_QUIRK)) {
3350         NSRange returnStringRange = [script rangeOfString:@"return "];
3351         if (returnStringRange.length && !returnStringRange.location)
3352             script = [script substringFromIndex:returnStringRange.location + returnStringRange.length];
3353     }
3354
3355     NSString *result = [[self mainFrame] _stringByEvaluatingJavaScriptFromString:script];
3356     // The only way stringByEvaluatingJavaScriptFromString can return nil is if the frame was removed by the script
3357     // Since there's no way to get rid of the main frame, result will never ever be nil here.
3358     ASSERT(result);
3359
3360     return result;
3361 }
3362
3363 - (WebScriptObject *)windowScriptObject
3364 {
3365     Frame* coreFrame = [self _mainCoreFrame];
3366     if (!coreFrame)
3367         return nil;
3368     return coreFrame->script()->windowScriptObject();
3369 }
3370
3371 // Get the appropriate user-agent string for a particular URL.
3372 - (NSString *)userAgentForURL:(NSURL *)url
3373 {
3374     if (_private->useSiteSpecificSpoofing) {
3375         // No current site-specific spoofs.
3376     }
3377
3378     if (_private->userAgent.isNull())
3379         _private->userAgent = [[self class] _standardUserAgentWithApplicationName:_private->applicationNameForUserAgent];
3380
3381     return _private->userAgent;
3382 }
3383
3384 - (void)setHostWindow:(NSWindow *)hostWindow
3385 {
3386     if (_private->closed && hostWindow)
3387         return;
3388     if (hostWindow == _private->hostWindow)
3389         return;
3390
3391     Frame* coreFrame = [self _mainCoreFrame];
3392     if (_private->usesDocumentViews) {
3393         for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
3394             [[[kit(frame) frameView] documentView] viewWillMoveToHostWindow:hostWindow];
3395     }
3396     if (_private->hostWindow && [self window] != _private->hostWindow)
3397         [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowWillCloseNotification object:_private->hostWindow];
3398     if (hostWindow)
3399         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillClose:) name:NSWindowWillCloseNotification object:hostWindow];
3400     [_private->hostWindow release];
3401     _private->hostWindow = [hostWindow retain];
3402     if (_private->usesDocumentViews) {
3403         for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
3404             [[[kit(frame) frameView] documentView] viewDidMoveToHostWindow];
3405     }
3406 }
3407
3408 - (NSWindow *)hostWindow
3409 {
3410     // -[WebView hostWindow] can sometimes be called from the WebView's [super dealloc] method
3411     // so we check here to make sure it's not null.
3412     if (!_private)
3413         return nil;
3414     
3415     return _private->hostWindow;
3416 }
3417
3418 - (NSView <WebDocumentView> *)documentViewAtWindowPoint:(NSPoint)point
3419 {
3420     return [[self _frameViewAtWindowPoint:point] documentView];
3421 }
3422
3423 - (NSDictionary *)_elementAtWindowPoint:(NSPoint)windowPoint
3424 {
3425     WebFrameView *frameView = [self _frameViewAtWindowPoint:windowPoint];
3426     if (!frameView)
3427         return nil;
3428     NSView <WebDocumentView> *documentView = [frameView documentView];
3429     if ([documentView conformsToProtocol:@protocol(WebDocumentElement)]) {
3430         NSPoint point = [documentView convertPoint:windowPoint fromView:nil];
3431         return [(NSView <WebDocumentElement> *)documentView elementAtPoint:point];
3432     }
3433     return [NSDictionary dictionaryWithObject:[frameView webFrame] forKey:WebElementFrameKey];
3434 }
3435
3436 - (NSDictionary *)elementAtPoint:(NSPoint)point
3437 {
3438     return [self _elementAtWindowPoint:[self convertPoint:point toView:nil]];
3439 }
3440
3441 // The following 2 internal NSView methods are called on the drag destination to make scrolling while dragging work.
3442 // Scrolling while dragging will only work if the drag destination is in a scroll view. The WebView is the drag destination. 
3443 // When dragging to a WebView, the document subview should scroll, but it doesn't because it is not the drag destination. 
3444 // Forward these calls to the document subview to make its scroll view scroll.
3445 - (void)_autoscrollForDraggingInfo:(id)draggingInfo timeDelta:(NSTimeInterval)repeatDelta
3446 {
3447     NSView <WebDocumentView> *documentView = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3448     [documentView _autoscrollForDraggingInfo:draggingInfo timeDelta:repeatDelta];
3449 }
3450
3451 - (BOOL)_shouldAutoscrollForDraggingInfo:(id)draggingInfo
3452 {
3453     NSView <WebDocumentView> *documentView = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3454     return [documentView _shouldAutoscrollForDraggingInfo:draggingInfo];
3455 }
3456
3457 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)draggingInfo
3458 {
3459     NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3460     WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]] ? (WebHTMLView*)view : nil);
3461     IntPoint client([draggingInfo draggingLocation]);
3462     IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
3463     DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
3464     return core(self)->dragController()->dragEntered(&dragData);
3465 }
3466
3467 - (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)draggingInfo
3468 {
3469     Page* page = core(self);
3470     if (!page)
3471         return NSDragOperationNone;
3472
3473     NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3474     WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]] ? (WebHTMLView*)view : nil);
3475     IntPoint client([draggingInfo draggingLocation]);
3476     IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
3477     DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
3478     return page->dragController()->dragUpdated(&dragData);
3479 }
3480
3481 - (void)draggingExited:(id <NSDraggingInfo>)draggingInfo
3482 {
3483     Page* page = core(self);
3484     if (!page)
3485         return;
3486
3487     NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3488     WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]] ? (WebHTMLView*)view : nil);
3489     IntPoint client([draggingInfo draggingLocation]);
3490     IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
3491     DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
3492     page->dragController()->dragExited(&dragData);
3493 }
3494
3495 - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)draggingInfo
3496 {
3497     return YES;
3498 }
3499
3500 - (BOOL)performDragOperation:(id <NSDraggingInfo>)draggingInfo
3501 {
3502     NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3503     WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]]? (WebHTMLView*)view : nil);
3504     IntPoint client([draggingInfo draggingLocation]);
3505     IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
3506     DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
3507     return core(self)->dragController()->performDrag(&dragData);
3508 }
3509
3510 - (NSView *)_hitTest:(NSPoint *)point dragTypes:(NSSet *)types
3511 {
3512     NSView *hitView = [super _hitTest:point dragTypes:types];
3513     if (!hitView && [[self superview] mouse:*point inRect:[self frame]])
3514         return self;
3515     return hitView;
3516 }
3517
3518 - (BOOL)acceptsFirstResponder
3519 {
3520     if (_private->usesDocumentViews)
3521         return [[[self mainFrame] frameView] acceptsFirstResponder];
3522
3523     // FIXME (Viewless): Need more code from WebHTMLView here.
3524     return YES;
3525 }
3526
3527 - (BOOL)becomeFirstResponder
3528 {
3529     if (_private->usesDocumentViews) {
3530         if (_private->becomingFirstResponder) {
3531             // Fix for unrepro infinite recursion reported in Radar 4448181. If we hit this assert on
3532             // a debug build, we should figure out what causes the problem and do a better fix.
3533             ASSERT_NOT_REACHED();
3534             return NO;
3535         }
3536         
3537         // This works together with setNextKeyView to splice the WebView into
3538         // the key loop similar to the way NSScrollView does this. Note that
3539         // WebFrameView has very similar code.
3540         NSWindow *window = [self window];
3541         WebFrameView *mainFrameView = [[self mainFrame] frameView];
3542
3543         NSResponder *previousFirstResponder = [[self window] _oldFirstResponderBeforeBecoming];
3544         BOOL fromOutside = ![previousFirstResponder isKindOfClass:[NSView class]] || (![(NSView *)previousFirstResponder isDescendantOf:self] && previousFirstResponder != self);
3545
3546         if ([window keyViewSelectionDirection] == NSSelectingPrevious) {
3547             NSView *previousValidKeyView = [self previousValidKeyView];
3548             if (previousValidKeyView != self && previousValidKeyView != mainFrameView) {
3549                 _private->becomingFirstResponder = YES;
3550                 _private->becomingFirstResponderFromOutside = fromOutside;
3551                 [window makeFirstResponder:previousValidKeyView];
3552                 _private->becomingFirstResponderFromOutside = NO;
3553                 _private->becomingFirstResponder = NO;
3554                 return YES;
3555             }
3556             return NO;
3557         }
3558
3559         if ([mainFrameView acceptsFirstResponder]) {
3560             _private->becomingFirstResponder = YES;
3561             _private->becomingFirstResponderFromOutside = fromOutside;
3562             [window makeFirstResponder:mainFrameView];
3563             _private->becomingFirstResponderFromOutside = NO;
3564             _private->becomingFirstResponder = NO;
3565             return YES;
3566         } 
3567
3568         return NO;
3569     }
3570
3571     // FIXME (Viewless): Need more code from WebHTMLView here.
3572     return YES;
3573 }
3574
3575 - (NSView *)_webcore_effectiveFirstResponder
3576 {
3577     if (_private && _private->usesDocumentViews) {
3578         if (WebFrameView *frameView = [[self mainFrame] frameView])
3579             return [frameView _webcore_effectiveFirstResponder];
3580     }
3581     return [super _webcore_effectiveFirstResponder];
3582 }
3583
3584 - (void)setNextKeyView:(NSView *)view
3585 {
3586     if (_private && _private->usesDocumentViews) {
3587         // This works together with becomeFirstResponder to splice the WebView into
3588         // the key loop similar to the way NSScrollView does this. Note that
3589         // WebFrameView has similar code.
3590         if (WebFrameView *mainFrameView = [[self mainFrame] frameView]) {
3591             [mainFrameView setNextKeyView:view];
3592             return;
3593         }
3594     }
3595
3596     [super setNextKeyView:view];
3597 }
3598
3599 static WebFrame *incrementFrame(WebFrame *frame, BOOL forward, BOOL wrapFlag)
3600 {
3601     Frame* coreFrame = core(frame);
3602     return kit(forward
3603         ? coreFrame->tree()->traverseNextWithWrap(wrapFlag)
3604         : coreFrame->tree()->traversePreviousWithWrap(wrapFlag));
3605 }
3606
3607 - (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag
3608 {
3609     return [self searchFor:string direction:forward caseSensitive:caseFlag wrap:wrapFlag startInSelection:NO];
3610 }
3611
3612 + (void)registerViewClass:(Class)viewClass representationClass:(Class)representationClass forMIMEType:(NSString *)MIMEType
3613 {
3614     [[WebFrameView _viewTypesAllowImageTypeOmission:YES] setObject:viewClass forKey:MIMEType];
3615     [[WebDataSource _repTypesAllowImageTypeOmission:YES] setObject:representationClass forKey:MIMEType];
3616     
3617     // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
3618     // in the WebCore MIMEType registry.  For now we're doing this in a safe, limited manner
3619     // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
3620     if ([viewClass class] == [WebHTMLView class])
3621         MIMETypeRegistry::getSupportedNonImageMIMETypes().add(MIMEType);
3622 }
3623
3624 - (void)setGroupName:(NSString *)groupName
3625 {
3626     if (!_private->page)
3627         return;
3628     _private->page->setGroupName(groupName);
3629 }
3630
3631 - (NSString *)groupName
3632 {
3633     if (!_private->page)
3634         return nil;
3635     return _private->page->groupName();
3636 }
3637
3638 - (double)estimatedProgress
3639 {
3640     if (!_private->page)
3641         return 0.0;
3642     return _private->page->progress()->estimatedProgress();
3643 }
3644
3645 - (NSArray *)pasteboardTypesForSelection
3646 {
3647     NSView <WebDocumentView> *documentView = [[[self _selectedOrMainFrame] frameView] documentView];
3648     if ([documentView conformsToProtocol:@protocol(WebDocumentSelection)]) {
3649         return [(NSView <WebDocumentSelection> *)documentView pasteboardTypesForSelection];
3650     }
3651     return [NSArray array];
3652 }
3653
3654 - (void)writeSelectionWithPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
3655 {
3656     WebFrame *frame = [self _selectedOrMainFrame];
3657     if (frame && [frame _hasSelection]) {
3658         NSView <WebDocumentView> *documentView = [[frame frameView] documentView];
3659         if ([documentView conformsToProtocol:@protocol(WebDocumentSelection)])
3660             [(NSView <WebDocumentSelection> *)documentView writeSelectionWithPasteboardTypes:types toPasteboard:pasteboard];
3661     }
3662 }
3663
3664 - (NSArray *)pasteboardTypesForElement:(NSDictionary *)element
3665 {
3666     if ([element objectForKey:WebElementImageURLKey] != nil) {
3667         return [NSPasteboard _web_writableTypesForImageIncludingArchive:([element objectForKey:WebElementDOMNodeKey] != nil)];
3668     } else if ([element objectForKey:WebElementLinkURLKey] != nil) {
3669         return [NSPasteboard _web_writableTypesForURL];
3670     } else if ([[element objectForKey:WebElementIsSelectedKey] boolValue]) {
3671         return [self pasteboardTypesForSelection];
3672     }
3673     return [NSArray array];
3674 }
3675
3676 - (void)writeElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
3677 {
3678     if ([element objectForKey:WebElementImageURLKey] != nil) {
3679         [self _writeImageForElement:element withPasteboardTypes:types toPasteboard:pasteboard];
3680     } else if ([element objectForKey:WebElementLinkURLKey] != nil) {
3681         [self _writeLinkElement:element withPasteboardTypes:types toPasteboard:pasteboard];
3682     } else if ([[element objectForKey:WebElementIsSelectedKey] boolValue]) {
3683         [self writeSelectionWithPasteboardTypes:types toPasteboard:pasteboard];
3684     }
3685 }
3686
3687 - (void)moveDragCaretToPoint:(NSPoint)point
3688 {
3689     if (Page* page = core(self))
3690         page->dragController()->placeDragCaret(IntPoint([self convertPoint:point toView:nil]));
3691 }
3692
3693 - (void)removeDragCaret
3694 {
3695     if (Page* page = core(self))
3696         page->dragController()->dragEnded();
3697 }
3698
3699 - (void)setMainFrameURL:(NSString *)URLString
3700 {
3701     [[self mainFrame] loadRequest: [NSURLRequest requestWithURL: [NSURL _web_URLWithDataAsString: URLString]]];
3702 }
3703
3704 - (NSString *)mainFrameURL
3705 {
3706     WebDataSource *ds;
3707     ds = [[self mainFrame] provisionalDataSource];
3708     if (!ds)
3709         ds = [[self mainFrame] _dataSource];
3710     return [[[ds request] URL] _web_originalDataAsString];
3711 }
3712
3713 - (BOOL)isLoading
3714 {
3715     LOG (Bindings, "isLoading = %d", (int)[self _isLoading]);
3716     return [self _isLoading];
3717 }
3718
3719 - (NSString *)mainFrameTitle
3720 {
3721     NSString *mainFrameTitle = [[[self mainFrame] _dataSource] pageTitle];
3722     return (mainFrameTitle != nil) ? mainFrameTitle : (NSString *)@"";
3723 }
3724
3725 - (NSImage *)mainFrameIcon
3726 {
3727     return [[WebIconDatabase sharedIconDatabase] iconForURL:[[[[self mainFrame] _dataSource] _URL] _web_originalDataAsString] withSize:WebIconSmallSize];
3728 }
3729
3730 - (DOMDocument *)mainFrameDocument
3731 {
3732     // only return the actual value if the state we're in gives NSTreeController
3733     // enough time to release its observers on the old model
3734     if (_private->mainFrameDocumentReady)
3735         return [[self mainFrame] DOMDocument];
3736     return nil;
3737 }
3738
3739 - (void)setDrawsBackground:(BOOL)drawsBackground
3740 {
3741     if (_private->drawsBackground == drawsBackground)
3742         return;
3743     _private->drawsBackground = drawsBackground;
3744     [[self mainFrame] _updateBackgroundAndUpdatesWhileOffscreen];
3745 }
3746
3747 - (BOOL)drawsBackground
3748 {
3749     // This method can be called beneath -[NSView dealloc] after we have cleared _private,
3750     // indirectly via -[WebFrameView viewDidMoveToWindow].
3751     return !_private || _private->drawsBackground;
3752 }
3753
3754 - (void)setShouldUpdateWhileOffscreen:(BOOL)updateWhileOffscreen
3755 {
3756     if (_private->shouldUpdateWhileOffscreen == updateWhileOffscreen)
3757         return;
3758     _private->shouldUpdateWhileOffscreen = updateWhileOffscreen;
3759     [[self mainFrame] _updateBackgroundAndUpdatesWhileOffscreen];
3760 }
3761
3762 - (BOOL)shouldUpdateWhileOffscreen
3763 {
3764     return _private->shouldUpdateWhileOffscreen;
3765 }
3766
3767 - (void)setCurrentNodeHighlight:(WebNodeHighlight *)nodeHighlight
3768 {
3769     id old = _private->currentNodeHighlight;
3770     _private->currentNodeHighlight = [nodeHighlight retain];
3771     [old release];
3772 }
3773