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