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