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