OSDN Git Service

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