OSDN Git Service

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