f8b72b74eeac82b1b7ebf1af11bab793a4a73567
[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         settings->setUserStyleSheetLocation([NSURL URLWithString:(location ? location : @"")]);
1305     } else
1306         settings->setUserStyleSheetLocation([NSURL URLWithString:@""]);
1307     settings->setNeedsAdobeFrameReloadingQuirk([self _needsAdobeFrameReloadingQuirk]);
1308     settings->setTreatsAnyTextCSSLinkAsStylesheet([self _needsLinkElementTextCSSQuirk]);
1309     settings->setNeedsKeyboardEventDisambiguationQuirks([self _needsKeyboardEventDisambiguationQuirks]);
1310     settings->setNeedsLeopardMailQuirks(runningLeopardMail());
1311     settings->setNeedsTigerMailQuirks(runningTigerMail());
1312     settings->setNeedsSiteSpecificQuirks(_private->useSiteSpecificSpoofing);
1313     settings->setWebArchiveDebugModeEnabled([preferences webArchiveDebugModeEnabled]);
1314     settings->setLocalFileContentSniffingEnabled([preferences localFileContentSniffingEnabled]);
1315     settings->setOfflineWebApplicationCacheEnabled([preferences offlineWebApplicationCacheEnabled]);
1316     settings->setZoomsTextOnly([preferences zoomsTextOnly]);
1317     settings->setXSSAuditorEnabled([preferences isXSSAuditorEnabled]);
1318     settings->setEnforceCSSMIMETypeInStrictMode(!WKAppVersionCheckLessThan(@"com.apple.iWeb", -1, 2.1));
1319     settings->setAcceleratedCompositingEnabled([preferences acceleratedCompositingEnabled]);
1320     settings->setShowDebugBorders([preferences showDebugBorders]);
1321     settings->setShowRepaintCounter([preferences showRepaintCounter]);
1322     settings->setPluginAllowedRunTime([preferences pluginAllowedRunTime]);
1323     settings->setWebGLEnabled([preferences webGLEnabled]);
1324 }
1325
1326 static inline IMP getMethod(id o, SEL s)
1327 {
1328     return [o respondsToSelector:s] ? [o methodForSelector:s] : 0;
1329 }
1330
1331 - (void)_cacheResourceLoadDelegateImplementations
1332 {
1333     WebResourceDelegateImplementationCache *cache = &_private->resourceLoadDelegateImplementations;
1334     id delegate = _private->resourceProgressDelegate;
1335
1336     if (!delegate) {
1337         bzero(cache, sizeof(WebResourceDelegateImplementationCache));
1338         return;
1339     }
1340
1341     cache->didCancelAuthenticationChallengeFunc = getMethod(delegate, @selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:));
1342     cache->didFailLoadingWithErrorFromDataSourceFunc = getMethod(delegate, @selector(webView:resource:didFailLoadingWithError:fromDataSource:));
1343     cache->didFinishLoadingFromDataSourceFunc = getMethod(delegate, @selector(webView:resource:didFinishLoadingFromDataSource:));
1344     cache->didLoadResourceFromMemoryCacheFunc = getMethod(delegate, @selector(webView:didLoadResourceFromMemoryCache:response:length:fromDataSource:));
1345     cache->didReceiveAuthenticationChallengeFunc = getMethod(delegate, @selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:));
1346     cache->didReceiveContentLengthFunc = getMethod(delegate, @selector(webView:resource:didReceiveContentLength:fromDataSource:));
1347     cache->didReceiveResponseFunc = getMethod(delegate, @selector(webView:resource:didReceiveResponse:fromDataSource:));
1348     cache->identifierForRequestFunc = getMethod(delegate, @selector(webView:identifierForInitialRequest:fromDataSource:));
1349     cache->plugInFailedWithErrorFunc = getMethod(delegate, @selector(webView:plugInFailedWithError:dataSource:));
1350     cache->willCacheResponseFunc = getMethod(delegate, @selector(webView:resource:willCacheResponse:fromDataSource:));
1351     cache->willSendRequestFunc = getMethod(delegate, @selector(webView:resource:willSendRequest:redirectResponse:fromDataSource:));
1352     cache->shouldUseCredentialStorageFunc = getMethod(delegate, @selector(webView:resource:shouldUseCredentialStorageForDataSource:));
1353 }
1354
1355 - (void)_cacheFrameLoadDelegateImplementations
1356 {
1357     WebFrameLoadDelegateImplementationCache *cache = &_private->frameLoadDelegateImplementations;
1358     id delegate = _private->frameLoadDelegate;
1359
1360     if (!delegate) {
1361         bzero(cache, sizeof(WebFrameLoadDelegateImplementationCache));
1362         return;
1363     }
1364
1365     cache->didCancelClientRedirectForFrameFunc = getMethod(delegate, @selector(webView:didCancelClientRedirectForFrame:));
1366     cache->didChangeLocationWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didChangeLocationWithinPageForFrame:));
1367     cache->didPushStateWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didPushStateWithinPageForFrame:));
1368     cache->didReplaceStateWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didReplaceStateWithinPageForFrame:));
1369     cache->didPopStateWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didPopStateWithinPageForFrame:));
1370     cache->didClearWindowObjectForFrameFunc = getMethod(delegate, @selector(webView:didClearWindowObject:forFrame:));
1371     cache->didClearWindowObjectForFrameInScriptWorldFunc = getMethod(delegate, @selector(webView:didClearWindowObjectForFrame:inScriptWorld:));
1372     cache->didClearInspectorWindowObjectForFrameFunc = getMethod(delegate, @selector(webView:didClearInspectorWindowObject:forFrame:));
1373     cache->didCommitLoadForFrameFunc = getMethod(delegate, @selector(webView:didCommitLoadForFrame:));
1374     cache->didFailLoadWithErrorForFrameFunc = getMethod(delegate, @selector(webView:didFailLoadWithError:forFrame:));
1375     cache->didFailProvisionalLoadWithErrorForFrameFunc = getMethod(delegate, @selector(webView:didFailProvisionalLoadWithError:forFrame:));
1376     cache->didFinishDocumentLoadForFrameFunc = getMethod(delegate, @selector(webView:didFinishDocumentLoadForFrame:));
1377     cache->didFinishLoadForFrameFunc = getMethod(delegate, @selector(webView:didFinishLoadForFrame:));
1378     cache->didFirstLayoutInFrameFunc = getMethod(delegate, @selector(webView:didFirstLayoutInFrame:));
1379     cache->didFirstVisuallyNonEmptyLayoutInFrameFunc = getMethod(delegate, @selector(webView:didFirstVisuallyNonEmptyLayoutInFrame:));
1380     cache->didHandleOnloadEventsForFrameFunc = getMethod(delegate, @selector(webView:didHandleOnloadEventsForFrame:));
1381     cache->didReceiveIconForFrameFunc = getMethod(delegate, @selector(webView:didReceiveIcon:forFrame:));
1382     cache->didReceiveServerRedirectForProvisionalLoadForFrameFunc = getMethod(delegate, @selector(webView:didReceiveServerRedirectForProvisionalLoadForFrame:));
1383     cache->didReceiveTitleForFrameFunc = getMethod(delegate, @selector(webView:didReceiveTitle:forFrame:));
1384     cache->didStartProvisionalLoadForFrameFunc = getMethod(delegate, @selector(webView:didStartProvisionalLoadForFrame:));
1385     cache->willCloseFrameFunc = getMethod(delegate, @selector(webView:willCloseFrame:));
1386     cache->willPerformClientRedirectToURLDelayFireDateForFrameFunc = getMethod(delegate, @selector(webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:));
1387     cache->windowScriptObjectAvailableFunc = getMethod(delegate, @selector(webView:windowScriptObjectAvailable:));
1388     cache->didDisplayInsecureContentFunc = getMethod(delegate, @selector(webViewDidDisplayInsecureContent:));
1389     cache->didRunInsecureContentFunc = getMethod(delegate, @selector(webView:didRunInsecureContent:));
1390 }
1391
1392 - (void)_cacheScriptDebugDelegateImplementations
1393 {
1394     WebScriptDebugDelegateImplementationCache *cache = &_private->scriptDebugDelegateImplementations;
1395     id delegate = _private->scriptDebugDelegate;
1396
1397     if (!delegate) {
1398         bzero(cache, sizeof(WebScriptDebugDelegateImplementationCache));
1399         return;
1400     }
1401
1402     cache->didParseSourceFunc = getMethod(delegate, @selector(webView:didParseSource:baseLineNumber:fromURL:sourceId:forWebFrame:));
1403     if (cache->didParseSourceFunc)
1404         cache->didParseSourceExpectsBaseLineNumber = YES;
1405     else
1406         cache->didParseSourceFunc = getMethod(delegate, @selector(webView:didParseSource:fromURL:sourceId:forWebFrame:));
1407
1408     cache->failedToParseSourceFunc = getMethod(delegate, @selector(webView:failedToParseSource:baseLineNumber:fromURL:withError:forWebFrame:));
1409     cache->didEnterCallFrameFunc = getMethod(delegate, @selector(webView:didEnterCallFrame:sourceId:line:forWebFrame:));
1410     cache->willExecuteStatementFunc = getMethod(delegate, @selector(webView:willExecuteStatement:sourceId:line:forWebFrame:));
1411     cache->willLeaveCallFrameFunc = getMethod(delegate, @selector(webView:willLeaveCallFrame:sourceId:line:forWebFrame:));
1412     cache->exceptionWasRaisedFunc = getMethod(delegate, @selector(webView:exceptionWasRaised:sourceId:line:forWebFrame:));
1413 }
1414
1415 - (void)_cacheHistoryDelegateImplementations
1416 {
1417     WebHistoryDelegateImplementationCache *cache = &_private->historyDelegateImplementations;
1418     id delegate = _private->historyDelegate;
1419
1420     if (!delegate) {
1421         bzero(cache, sizeof(WebHistoryDelegateImplementationCache));
1422         return;
1423     }
1424
1425     cache->navigatedFunc = getMethod(delegate, @selector(webView:didNavigateWithNavigationData:inFrame:));
1426     cache->clientRedirectFunc = getMethod(delegate, @selector(webView:didPerformClientRedirectFromURL:toURL:inFrame:));
1427     cache->serverRedirectFunc = getMethod(delegate, @selector(webView:didPerformServerRedirectFromURL:toURL:inFrame:));
1428     cache->setTitleFunc = getMethod(delegate, @selector(webView:updateHistoryTitle:forURL:));
1429     cache->populateVisitedLinksFunc = getMethod(delegate, @selector(populateVisitedLinksForWebView:));
1430 }
1431
1432 - (id)_policyDelegateForwarder
1433 {
1434     if (!_private->policyDelegateForwarder)
1435         _private->policyDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->policyDelegate defaultTarget:[WebDefaultPolicyDelegate sharedPolicyDelegate] catchExceptions:_private->catchesDelegateExceptions];
1436     return _private->policyDelegateForwarder;
1437 }
1438
1439 - (id)_UIDelegateForwarder
1440 {
1441     if (!_private->UIDelegateForwarder)
1442         _private->UIDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->UIDelegate defaultTarget:[WebDefaultUIDelegate sharedUIDelegate] catchExceptions:_private->catchesDelegateExceptions];
1443     return _private->UIDelegateForwarder;
1444 }
1445
1446 - (id)_editingDelegateForwarder
1447 {
1448     // This can be called during window deallocation by QTMovieView in the QuickTime Cocoa Plug-in.
1449     // Not sure if that is a bug or not.
1450     if (!_private)
1451         return nil;
1452
1453     if (!_private->editingDelegateForwarder)
1454         _private->editingDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->editingDelegate defaultTarget:[WebDefaultEditingDelegate sharedEditingDelegate] catchExceptions:_private->catchesDelegateExceptions];
1455     return _private->editingDelegateForwarder;
1456 }
1457
1458 - (void)_closeWindow
1459 {
1460     [[self _UIDelegateForwarder] webViewClose:self];
1461 }
1462
1463 + (void)_unregisterViewClassAndRepresentationClassForMIMEType:(NSString *)MIMEType
1464 {
1465     [[WebFrameView _viewTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType];
1466     [[WebDataSource _repTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType];
1467     
1468     // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
1469     // in the WebCore MIMEType registry.  For now we're doing this in a safe, limited manner
1470     // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
1471     MIMETypeRegistry::getSupportedNonImageMIMETypes().remove(MIMEType);
1472 }
1473
1474 + (void)_registerViewClass:(Class)viewClass representationClass:(Class)representationClass forURLScheme:(NSString *)URLScheme
1475 {
1476     NSString *MIMEType = [self _generatedMIMETypeForURLScheme:URLScheme];
1477     [self registerViewClass:viewClass representationClass:representationClass forMIMEType:MIMEType];
1478
1479     // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
1480     // in the WebCore MIMEType registry.  For now we're doing this in a safe, limited manner
1481     // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
1482     if ([viewClass class] == [WebHTMLView class])
1483         MIMETypeRegistry::getSupportedNonImageMIMETypes().add(MIMEType);
1484     
1485     // This is used to make _representationExistsForURLScheme faster.
1486     // Without this set, we'd have to create the MIME type each time.
1487     if (schemesWithRepresentationsSet == nil) {
1488         schemesWithRepresentationsSet = [[NSMutableSet alloc] init];
1489     }
1490     [schemesWithRepresentationsSet addObject:[[[URLScheme lowercaseString] copy] autorelease]];
1491 }
1492
1493 + (NSString *)_generatedMIMETypeForURLScheme:(NSString *)URLScheme
1494 {
1495     return [@"x-apple-web-kit/" stringByAppendingString:[URLScheme lowercaseString]];
1496 }
1497
1498 + (BOOL)_representationExistsForURLScheme:(NSString *)URLScheme
1499 {
1500     return [schemesWithRepresentationsSet containsObject:[URLScheme lowercaseString]];
1501 }
1502
1503 + (BOOL)_canHandleRequest:(NSURLRequest *)request forMainFrame:(BOOL)forMainFrame
1504 {
1505     // FIXME: If <rdar://problem/5217309> gets fixed, this check can be removed.
1506     if (!request)
1507         return NO;
1508
1509     if ([NSURLConnection canHandleRequest:request])
1510         return YES;
1511
1512     NSString *scheme = [[request URL] scheme];
1513
1514     // Representations for URL schemes work at the top level.
1515     if (forMainFrame && [self _representationExistsForURLScheme:scheme])
1516         return YES;
1517         
1518     return [scheme _webkit_isCaseInsensitiveEqualToString:@"applewebdata"];
1519 }
1520
1521 + (BOOL)_canHandleRequest:(NSURLRequest *)request
1522 {
1523     return [self _canHandleRequest:request forMainFrame:YES];
1524 }
1525
1526 + (NSString *)_decodeData:(NSData *)data
1527 {
1528     HTMLNames::init(); // this method is used for importing bookmarks at startup, so HTMLNames are likely to be uninitialized yet
1529     RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("text/html"); // bookmark files are HTML
1530     String result = decoder->decode(static_cast<const char*>([data bytes]), [data length]);
1531     result += decoder->flush();
1532     return result;
1533 }
1534
1535 - (void)_pushPerformingProgrammaticFocus
1536 {
1537     _private->programmaticFocusCount++;
1538 }
1539
1540 - (void)_popPerformingProgrammaticFocus
1541 {
1542     _private->programmaticFocusCount--;
1543 }
1544
1545 - (BOOL)_isPerformingProgrammaticFocus
1546 {
1547     return _private->programmaticFocusCount != 0;
1548 }
1549
1550 - (void)_didChangeValueForKey: (NSString *)key
1551 {
1552     LOG (Bindings, "calling didChangeValueForKey: %@", key);
1553     [self didChangeValueForKey: key];
1554 }
1555
1556 - (void)_willChangeValueForKey: (NSString *)key
1557 {
1558     LOG (Bindings, "calling willChangeValueForKey: %@", key);
1559     [self willChangeValueForKey: key];
1560 }
1561
1562 + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key {
1563     static NSSet *manualNotifyKeys = nil;
1564     if (!manualNotifyKeys)
1565         manualNotifyKeys = [[NSSet alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey,
1566             _WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, _WebMainFrameDocumentKey,
1567             nil];
1568     if ([manualNotifyKeys containsObject:key])
1569         return NO;
1570     return YES;
1571 }
1572
1573 - (NSArray *)_declaredKeys {
1574     static NSArray *declaredKeys = nil;
1575     if (!declaredKeys)
1576         declaredKeys = [[NSArray alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey,
1577             _WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, _WebMainFrameDocumentKey, nil];
1578     return declaredKeys;
1579 }
1580
1581 - (void)setObservationInfo:(void *)info
1582 {
1583     _private->observationInfo = info;
1584 }
1585
1586 - (void *)observationInfo
1587 {
1588     return _private->observationInfo;
1589 }
1590
1591 - (void)_willChangeBackForwardKeys
1592 {
1593     [self _willChangeValueForKey: _WebCanGoBackKey];
1594     [self _willChangeValueForKey: _WebCanGoForwardKey];
1595 }
1596
1597 - (void)_didChangeBackForwardKeys
1598 {
1599     [self _didChangeValueForKey: _WebCanGoBackKey];
1600     [self _didChangeValueForKey: _WebCanGoForwardKey];
1601 }
1602
1603 - (void)_didStartProvisionalLoadForFrame:(WebFrame *)frame
1604 {
1605     [self _willChangeBackForwardKeys];
1606     if (frame == [self mainFrame]){
1607         // Force an observer update by sending a will/did.
1608         [self _willChangeValueForKey: _WebIsLoadingKey];
1609         [self _didChangeValueForKey: _WebIsLoadingKey];
1610
1611         [self _willChangeValueForKey: _WebMainFrameURLKey];
1612     }
1613
1614     [NSApp setWindowsNeedUpdate:YES];
1615 }
1616
1617 - (void)_didCommitLoadForFrame:(WebFrame *)frame
1618 {
1619     if (frame == [self mainFrame])
1620         [self _didChangeValueForKey: _WebMainFrameURLKey];
1621     [NSApp setWindowsNeedUpdate:YES];
1622 }
1623
1624 - (void)_didFinishLoadForFrame:(WebFrame *)frame
1625 {
1626     [self _didChangeBackForwardKeys];
1627     if (frame == [self mainFrame]){
1628         // Force an observer update by sending a will/did.
1629         [self _willChangeValueForKey: _WebIsLoadingKey];
1630         [self _didChangeValueForKey: _WebIsLoadingKey];
1631     }
1632     [NSApp setWindowsNeedUpdate:YES];
1633 }
1634
1635 - (void)_didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
1636 {
1637     [self _didChangeBackForwardKeys];
1638     if (frame == [self mainFrame]){
1639         // Force an observer update by sending a will/did.
1640         [self _willChangeValueForKey: _WebIsLoadingKey];
1641         [self _didChangeValueForKey: _WebIsLoadingKey];
1642     }
1643     [NSApp setWindowsNeedUpdate:YES];
1644 }
1645
1646 - (void)_didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
1647 {
1648     [self _didChangeBackForwardKeys];
1649     if (frame == [self mainFrame]){
1650         // Force an observer update by sending a will/did.
1651         [self _willChangeValueForKey: _WebIsLoadingKey];
1652         [self _didChangeValueForKey: _WebIsLoadingKey];
1653         
1654         [self _didChangeValueForKey: _WebMainFrameURLKey];
1655     }
1656     [NSApp setWindowsNeedUpdate:YES];
1657 }
1658
1659 - (NSCachedURLResponse *)_cachedResponseForURL:(NSURL *)URL
1660 {
1661     NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:URL];
1662     [request _web_setHTTPUserAgent:[self userAgentForURL:URL]];
1663     NSCachedURLResponse *cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:request];
1664     [request release];
1665     return cachedResponse;
1666 }
1667
1668 - (void)_writeImageForElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
1669 {
1670     NSURL *linkURL = [element objectForKey:WebElementLinkURLKey];
1671     DOMElement *domElement = [element objectForKey:WebElementDOMNodeKey];
1672     [pasteboard _web_writeImage:(NSImage *)(domElement ? nil : [element objectForKey:WebElementImageKey])
1673                         element:domElement
1674                             URL:linkURL ? linkURL : (NSURL *)[element objectForKey:WebElementImageURLKey]
1675                           title:[element objectForKey:WebElementImageAltStringKey] 
1676                         archive:[[element objectForKey:WebElementDOMNodeKey] webArchive]
1677                           types:types
1678                          source:nil];
1679 }
1680
1681 - (void)_writeLinkElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
1682 {
1683     [pasteboard _web_writeURL:[element objectForKey:WebElementLinkURLKey]
1684                      andTitle:[element objectForKey:WebElementLinkLabelKey]
1685                         types:types];
1686 }
1687
1688 - (void)_setInitiatedDrag:(BOOL)initiatedDrag
1689 {
1690     if (!_private->page)
1691         return;
1692     _private->page->dragController()->setDidInitiateDrag(initiatedDrag);
1693 }
1694
1695 #if ENABLE(DASHBOARD_SUPPORT)
1696
1697 #define DASHBOARD_CONTROL_LABEL @"control"
1698
1699 - (void)_addControlRect:(NSRect)bounds clip:(NSRect)clip fromView:(NSView *)view toDashboardRegions:(NSMutableDictionary *)regions
1700 {
1701     NSRect adjustedBounds = bounds;
1702     adjustedBounds.origin = [self convertPoint:bounds.origin fromView:view];
1703     adjustedBounds.origin.y = [self bounds].size.height - adjustedBounds.origin.y;
1704     adjustedBounds.size = bounds.size;
1705
1706     NSRect adjustedClip;
1707     adjustedClip.origin = [self convertPoint:clip.origin fromView:view];
1708     adjustedClip.origin.y = [self bounds].size.height - adjustedClip.origin.y;
1709     adjustedClip.size = clip.size;
1710
1711     WebDashboardRegion *region = [[WebDashboardRegion alloc] initWithRect:adjustedBounds 
1712         clip:adjustedClip type:WebDashboardRegionTypeScrollerRectangle];
1713     NSMutableArray *scrollerRegions = [regions objectForKey:DASHBOARD_CONTROL_LABEL];
1714     if (!scrollerRegions) {
1715         scrollerRegions = [[NSMutableArray alloc] init];
1716         [regions setObject:scrollerRegions forKey:DASHBOARD_CONTROL_LABEL];
1717         [scrollerRegions release];
1718     }
1719     [scrollerRegions addObject:region];
1720     [region release];
1721 }
1722
1723 - (void)_addScrollerDashboardRegionsForFrameView:(FrameView*)frameView dashboardRegions:(NSMutableDictionary *)regions
1724 {    
1725     NSView *documentView = [[kit(frameView->frame()) frameView] documentView];
1726
1727     const HashSet<RefPtr<Widget> >* children = frameView->children();
1728     HashSet<RefPtr<Widget> >::const_iterator end = children->end();
1729     for (HashSet<RefPtr<Widget> >::const_iterator it = children->begin(); it != end; ++it) {
1730         Widget* widget = (*it).get();
1731         if (widget->isFrameView()) {
1732             [self _addScrollerDashboardRegionsForFrameView:static_cast<FrameView*>(widget) dashboardRegions:regions];
1733             continue;
1734         }
1735
1736         if (!widget->isScrollbar())
1737             continue;
1738
1739         // FIXME: This should really pass an appropriate clip, but our first try got it wrong, and
1740         // it's not common to need this to be correct in Dashboard widgets.
1741         NSRect bounds = widget->frameRect();
1742         [self _addControlRect:bounds clip:bounds fromView:documentView toDashboardRegions:regions];
1743     }
1744 }
1745
1746 - (void)_addScrollerDashboardRegions:(NSMutableDictionary *)regions from:(NSArray *)views
1747 {
1748     // Add scroller regions for NSScroller and WebCore scrollbars
1749     NSUInteger count = [views count];
1750     for (NSUInteger i = 0; i < count; i++) {
1751         NSView *view = [views objectAtIndex:i];
1752         
1753         if ([view isKindOfClass:[WebHTMLView class]]) {
1754             if (Frame* coreFrame = core([(WebHTMLView*)view _frame])) {
1755                 if (FrameView* coreView = coreFrame->view())
1756                     [self _addScrollerDashboardRegionsForFrameView:coreView dashboardRegions:regions];
1757             }
1758         } else if ([view isKindOfClass:[NSScroller class]]) {
1759             // AppKit places absent scrollers at -100,-100
1760             if ([view frame].origin.y < 0)
1761                 continue;
1762             [self _addControlRect:[view bounds] clip:[view visibleRect] fromView:view toDashboardRegions:regions];
1763         }
1764         [self _addScrollerDashboardRegions:regions from:[view subviews]];
1765     }
1766 }
1767
1768 - (void)_addScrollerDashboardRegions:(NSMutableDictionary *)regions
1769 {
1770     [self _addScrollerDashboardRegions:regions from:[self subviews]];
1771 }
1772
1773 - (NSDictionary *)_dashboardRegions
1774 {
1775     // Only return regions from main frame.
1776     Frame* mainFrame = [self _mainCoreFrame];
1777     if (!mainFrame)
1778         return nil;
1779     NSMutableDictionary *regions = mainFrame->dashboardRegionsDictionary();
1780     [self _addScrollerDashboardRegions:regions];
1781     return regions;
1782 }
1783
1784 - (void)_setDashboardBehavior:(WebDashboardBehavior)behavior to:(BOOL)flag
1785 {
1786     // FIXME: Remove this blanket assignment once Dashboard and Dashcode implement 
1787     // specific support for the backward compatibility mode flag.
1788     if (behavior == WebDashboardBehaviorAllowWheelScrolling && flag == NO && _private->page)
1789         _private->page->settings()->setUsesDashboardBackwardCompatibilityMode(true);
1790     
1791     switch (behavior) {
1792         case WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows: {
1793             _private->dashboardBehaviorAlwaysSendMouseEventsToAllWindows = flag;
1794             break;
1795         }
1796         case WebDashboardBehaviorAlwaysSendActiveNullEventsToPlugIns: {
1797             _private->dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns = flag;
1798             break;
1799         }
1800         case WebDashboardBehaviorAlwaysAcceptsFirstMouse: {
1801             _private->dashboardBehaviorAlwaysAcceptsFirstMouse = flag;
1802             break;
1803         }
1804         case WebDashboardBehaviorAllowWheelScrolling: {
1805             _private->dashboardBehaviorAllowWheelScrolling = flag;
1806             break;
1807         }
1808         case WebDashboardBehaviorUseBackwardCompatibilityMode: {
1809             if (_private->page)
1810                 _private->page->settings()->setUsesDashboardBackwardCompatibilityMode(flag);
1811             break;
1812         }
1813     }
1814 }
1815
1816 - (BOOL)_dashboardBehavior:(WebDashboardBehavior)behavior
1817 {
1818     switch (behavior) {
1819         case WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows: {
1820             return _private->dashboardBehaviorAlwaysSendMouseEventsToAllWindows;
1821         }
1822         case WebDashboardBehaviorAlwaysSendActiveNullEventsToPlugIns: {
1823             return _private->dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns;
1824         }
1825         case WebDashboardBehaviorAlwaysAcceptsFirstMouse: {
1826             return _private->dashboardBehaviorAlwaysAcceptsFirstMouse;
1827         }
1828         case WebDashboardBehaviorAllowWheelScrolling: {
1829             return _private->dashboardBehaviorAllowWheelScrolling;
1830         }
1831         case WebDashboardBehaviorUseBackwardCompatibilityMode: {
1832             return _private->page && _private->page->settings()->usesDashboardBackwardCompatibilityMode();
1833         }
1834     }
1835     return NO;
1836 }
1837
1838 #endif /* ENABLE(DASHBOARD_SUPPORT) */
1839
1840 + (void)_setShouldUseFontSmoothing:(BOOL)f
1841 {
1842     Font::setShouldUseSmoothing(f);
1843 }
1844
1845 + (BOOL)_shouldUseFontSmoothing
1846 {
1847     return Font::shouldUseSmoothing();
1848 }
1849
1850 + (void)_setUsesTestModeFocusRingColor:(BOOL)f
1851 {
1852     setUsesTestModeFocusRingColor(f);
1853 }
1854
1855 + (BOOL)_usesTestModeFocusRingColor
1856 {
1857     return usesTestModeFocusRingColor();
1858 }
1859
1860 - (void)setAlwaysShowVerticalScroller:(BOOL)flag
1861 {
1862     WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
1863     if (flag) {
1864         [scrollview setVerticalScrollingMode:ScrollbarAlwaysOn andLock:YES];
1865     } else {
1866         [scrollview setVerticalScrollingModeLocked:NO];
1867         [scrollview setVerticalScrollingMode:ScrollbarAuto andLock:NO];
1868     }
1869 }
1870
1871 - (BOOL)alwaysShowVerticalScroller
1872 {
1873     WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
1874     return [scrollview verticalScrollingModeLocked] && [scrollview verticalScrollingMode] == ScrollbarAlwaysOn;
1875 }
1876
1877 - (void)setAlwaysShowHorizontalScroller:(BOOL)flag
1878 {
1879     WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
1880     if (flag) {
1881         [scrollview setHorizontalScrollingMode:ScrollbarAlwaysOn andLock:YES];
1882     } else {
1883         [scrollview setHorizontalScrollingModeLocked:NO];
1884         [scrollview setHorizontalScrollingMode:ScrollbarAuto andLock:NO];
1885     }
1886 }
1887
1888 - (void)setProhibitsMainFrameScrolling:(BOOL)prohibits
1889 {
1890     if (Frame* mainFrame = [self _mainCoreFrame])
1891         mainFrame->view()->setProhibitsScrolling(prohibits);
1892 }
1893
1894 - (BOOL)alwaysShowHorizontalScroller
1895 {
1896     WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
1897     return [scrollview horizontalScrollingModeLocked] && [scrollview horizontalScrollingMode] == ScrollbarAlwaysOn;
1898 }
1899
1900 - (void)_setInViewSourceMode:(BOOL)flag
1901 {
1902     if (Frame* mainFrame = [self _mainCoreFrame])
1903         mainFrame->setInViewSourceMode(flag);
1904 }
1905
1906 - (BOOL)_inViewSourceMode
1907 {
1908     Frame* mainFrame = [self _mainCoreFrame];
1909     return mainFrame && mainFrame->inViewSourceMode();
1910 }
1911
1912 - (void)_setUseFastImageScalingMode:(BOOL)flag
1913 {
1914     if (_private->page && _private->page->inLowQualityImageInterpolationMode() != flag) {
1915         _private->page->setInLowQualityImageInterpolationMode(flag);
1916         [self setNeedsDisplay:YES];
1917     }
1918 }
1919
1920 - (BOOL)_inFastImageScalingMode
1921 {
1922     if (_private->page)
1923         return _private->page->inLowQualityImageInterpolationMode();
1924     return NO;
1925 }
1926
1927 - (BOOL)_cookieEnabled
1928 {
1929     if (_private->page)
1930         return _private->page->cookieEnabled();
1931     return YES;
1932 }
1933
1934 - (void)_setCookieEnabled:(BOOL)enable
1935 {
1936     if (_private->page)
1937         _private->page->setCookieEnabled(enable);
1938 }
1939
1940 - (void)_setAdditionalWebPlugInPaths:(NSArray *)newPaths
1941 {
1942     if (!_private->pluginDatabase)
1943         _private->pluginDatabase = [[WebPluginDatabase alloc] init];
1944         
1945     [_private->pluginDatabase setPlugInPaths:newPaths];
1946     [_private->pluginDatabase refresh];
1947 }
1948
1949 - (void)_attachScriptDebuggerToAllFrames
1950 {
1951     for (Frame* frame = [self _mainCoreFrame]; frame; frame = frame->tree()->traverseNext())
1952         [kit(frame) _attachScriptDebugger];
1953 }
1954
1955 - (void)_detachScriptDebuggerFromAllFrames
1956 {
1957     for (Frame* frame = [self _mainCoreFrame]; frame; frame = frame->tree()->traverseNext())
1958         [kit(frame) _detachScriptDebugger];
1959 }
1960
1961 - (void)setBackgroundColor:(NSColor *)backgroundColor
1962 {
1963     if ([_private->backgroundColor isEqual:backgroundColor])
1964         return;
1965
1966     id old = _private->backgroundColor;
1967     _private->backgroundColor = [backgroundColor retain];
1968     [old release];
1969
1970     [[self mainFrame] _updateBackgroundAndUpdatesWhileOffscreen];
1971 }
1972
1973 - (NSColor *)backgroundColor
1974 {
1975     return _private->backgroundColor;
1976 }
1977
1978 - (BOOL)defersCallbacks
1979 {
1980     if (!_private->page)
1981         return NO;
1982     return _private->page->defersLoading();
1983 }
1984
1985 - (void)setDefersCallbacks:(BOOL)defer
1986 {
1987     if (!_private->page)
1988         return;
1989     return _private->page->setDefersLoading(defer);
1990 }
1991
1992 // For backwards compatibility with the WebBackForwardList API, we honor both
1993 // a per-WebView and a per-preferences setting for whether to use the page cache.
1994
1995 - (BOOL)usesPageCache
1996 {
1997     return _private->usesPageCache && [[self preferences] usesPageCache];
1998 }
1999
2000 - (void)setUsesPageCache:(BOOL)usesPageCache
2001 {
2002     _private->usesPageCache = usesPageCache;
2003
2004     // Post a notification so the WebCore settings update.
2005     [[self preferences] _postPreferencesChangesNotification];
2006 }
2007
2008 - (WebHistoryItem *)_globalHistoryItem
2009 {
2010     if (!_private->page)
2011         return nil;
2012     return kit(_private->page->globalHistoryItem());
2013 }
2014
2015 - (WebTextIterator *)textIteratorForRect:(NSRect)rect
2016 {
2017     IntPoint rectStart(rect.origin.x, rect.origin.y);
2018     IntPoint rectEnd(rect.origin.x + rect.size.width, rect.origin.y + rect.size.height);
2019     
2020     Frame* coreFrame = [self _mainCoreFrame];
2021     if (!coreFrame)
2022         return nil;
2023     
2024     VisibleSelection selectionInsideRect(coreFrame->visiblePositionForPoint(rectStart), coreFrame->visiblePositionForPoint(rectEnd));
2025     
2026     return [[[WebTextIterator alloc] initWithRange:kit(selectionInsideRect.toNormalizedRange().get())] autorelease];
2027 }
2028
2029 - (void)handleAuthenticationForResource:(id)identifier challenge:(NSURLAuthenticationChallenge *)challenge fromDataSource:(WebDataSource *)dataSource 
2030 {
2031     NSWindow *window = [self hostWindow] ? [self hostWindow] : [self window]; 
2032     [[WebPanelAuthenticationHandler sharedHandler] startAuthentication:challenge window:window]; 
2033
2034
2035 - (void)_clearUndoRedoOperations
2036 {
2037     if (!_private->page)
2038         return;
2039     _private->page->clearUndoRedoOperations();
2040 }
2041
2042 - (void)_setCatchesDelegateExceptions:(BOOL)f
2043 {
2044     _private->catchesDelegateExceptions = f;
2045 }
2046
2047 - (BOOL)_catchesDelegateExceptions
2048 {
2049     return _private->catchesDelegateExceptions;
2050 }
2051
2052 - (void)_executeCoreCommandByName:(NSString *)name value:(NSString *)value
2053 {
2054     Frame* coreFrame = [self _mainCoreFrame];
2055     if (!coreFrame)
2056         return;
2057     coreFrame->editor()->command(name).execute(value);
2058 }
2059
2060 - (void)_setCustomHTMLTokenizerTimeDelay:(double)timeDelay
2061 {
2062     if (!_private->page)
2063         return;
2064     return _private->page->setCustomHTMLTokenizerTimeDelay(timeDelay);
2065 }
2066
2067 - (void)_setCustomHTMLTokenizerChunkSize:(int)chunkSize
2068 {
2069     if (!_private->page)
2070         return;
2071     return _private->page->setCustomHTMLTokenizerChunkSize(chunkSize);
2072 }
2073
2074 - (void)_clearMainFrameName
2075 {
2076     _private->page->mainFrame()->tree()->clearName();
2077 }
2078
2079 - (void)setSelectTrailingWhitespaceEnabled:(BOOL)flag
2080 {
2081     _private->selectTrailingWhitespaceEnabled = flag;
2082     if (flag)
2083         [self setSmartInsertDeleteEnabled:false];
2084 }
2085
2086 - (BOOL)isSelectTrailingWhitespaceEnabled
2087 {
2088     return _private->selectTrailingWhitespaceEnabled;
2089 }
2090
2091 - (void)setMemoryCacheDelegateCallsEnabled:(BOOL)enabled
2092 {
2093     _private->page->setMemoryCacheClientCallsEnabled(enabled);
2094 }
2095
2096 - (BOOL)areMemoryCacheDelegateCallsEnabled
2097 {
2098     return _private->page->areMemoryCacheClientCallsEnabled();
2099 }
2100
2101 - (void)_setJavaScriptURLsAreAllowed:(BOOL)areAllowed
2102 {
2103     _private->page->setJavaScriptURLsAreAllowed(areAllowed);
2104 }
2105
2106 + (NSCursor *)_pointingHandCursor
2107 {
2108     return handCursor().impl();
2109 }
2110
2111 - (BOOL)_postsAcceleratedCompositingNotifications
2112 {
2113 #if USE(ACCELERATED_COMPOSITING)
2114     return _private->postsAcceleratedCompositingNotifications;
2115 #else
2116     return NO;
2117 #endif
2118
2119 }
2120 - (void)_setPostsAcceleratedCompositingNotifications:(BOOL)flag
2121 {
2122 #if USE(ACCELERATED_COMPOSITING)
2123     _private->postsAcceleratedCompositingNotifications = flag;
2124 #endif
2125 }
2126
2127 - (BOOL)_isUsingAcceleratedCompositing
2128 {
2129 #if USE(ACCELERATED_COMPOSITING)
2130     Frame* coreFrame = [self _mainCoreFrame];
2131     if (_private->usesDocumentViews) {
2132         for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
2133             NSView *documentView = [[kit(frame) frameView] documentView];
2134             if ([documentView isKindOfClass:[WebHTMLView class]] && [(WebHTMLView *)documentView _isUsingAcceleratedCompositing])
2135                 return YES;
2136         }
2137     }
2138
2139     return NO;
2140 #else
2141     return NO;
2142 #endif
2143 }
2144
2145 static WebBaseNetscapePluginView *_pluginViewForNode(DOMNode *node)
2146 {
2147     if (!node)
2148         return nil;
2149     
2150     Node* coreNode = core(node);
2151     if (!coreNode)
2152         return nil;
2153     
2154     RenderObject* renderer = coreNode->renderer();
2155     if (!renderer || !renderer->isWidget())
2156         return nil;
2157     
2158     Widget* widget = toRenderWidget(renderer)->widget();
2159     if (!widget || !widget->platformWidget())
2160         return nil;
2161     
2162     NSView *view = widget->platformWidget();
2163     if (![view isKindOfClass:[WebBaseNetscapePluginView class]])
2164         return nil;
2165     
2166     return (WebBaseNetscapePluginView *)view;
2167 }
2168
2169 + (BOOL)_isNodeHaltedPlugin:(DOMNode *)node
2170 {
2171     return [_pluginViewForNode(node) isHalted];
2172 }
2173
2174 + (BOOL)_hasPluginForNodeBeenHalted:(DOMNode *)node
2175 {
2176     return [_pluginViewForNode(node) hasBeenHalted];
2177 }
2178 + (void)_restartHaltedPluginForNode:(DOMNode *)node
2179 {
2180     if (!node)
2181         return;
2182     
2183     [_pluginViewForNode(node) resumeFromHalt];
2184 }
2185
2186 - (NSPasteboard *)_insertionPasteboard
2187 {
2188     return _private ? _private->insertionPasteboard : nil;
2189 }
2190
2191 + (void)_whiteListAccessFromOrigin:(NSString *)sourceOrigin destinationProtocol:(NSString *)destinationProtocol destinationHost:(NSString *)destinationHost allowDestinationSubdomains:(BOOL)allowDestinationSubdomains
2192 {
2193     SecurityOrigin::whiteListAccessFromOrigin(*SecurityOrigin::createFromString(sourceOrigin), destinationProtocol, destinationHost, allowDestinationSubdomains);
2194 }
2195
2196 +(void)_resetOriginAccessWhiteLists
2197 {
2198     SecurityOrigin::resetOriginAccessWhiteLists();
2199 }
2200
2201 - (void)_updateActiveState
2202 {
2203     if (_private && _private->page)
2204         _private->page->focusController()->setActive([[self window] isKeyWindow]);
2205 }
2206
2207 static PassOwnPtr<Vector<String> > toStringVector(NSArray* patterns)
2208 {
2209     // Convert the patterns into Vectors.
2210     NSUInteger count = [patterns count];
2211     if (count == 0)
2212         return 0;
2213     Vector<String>* patternsVector = new Vector<String>;
2214     for (NSUInteger i = 0; i < count; ++i) {
2215         id entry = [patterns objectAtIndex:i];
2216         if ([entry isKindOfClass:[NSString class]])
2217             patternsVector->append(String((NSString*)entry));
2218     }
2219     return patternsVector;
2220 }
2221
2222 + (void)_addUserScriptToGroup:(NSString *)groupName world:(WebScriptWorld *)world source:(NSString *)source url:(NSURL *)url
2223                     whitelist:(NSArray *)whitelist blacklist:(NSArray *)blacklist injectionTime:(WebUserScriptInjectionTime)injectionTime
2224 {
2225     String group(groupName);
2226     if (group.isEmpty())
2227         return;
2228     
2229     PageGroup* pageGroup = PageGroup::pageGroup(group);
2230     if (!pageGroup)
2231         return;
2232     
2233     pageGroup->addUserScriptToWorld(core(world), source, url, toStringVector(whitelist), toStringVector(blacklist), 
2234                                     injectionTime == WebInjectAtDocumentStart ? InjectAtDocumentStart : InjectAtDocumentEnd);
2235 }
2236
2237 + (void)_addUserStyleSheetToGroup:(NSString *)groupName world:(WebScriptWorld *)world source:(NSString *)source url:(NSURL *)url
2238                         whitelist:(NSArray *)whitelist blacklist:(NSArray *)blacklist
2239 {
2240     String group(groupName);
2241     if (group.isEmpty())
2242         return;
2243     
2244     PageGroup* pageGroup = PageGroup::pageGroup(group);
2245     if (!pageGroup)
2246         return;
2247
2248     pageGroup->addUserStyleSheetToWorld(core(world), source, url, toStringVector(whitelist), toStringVector(blacklist));
2249 }
2250
2251 + (void)_removeUserScriptFromGroup:(NSString *)groupName world:(WebScriptWorld *)world url:(NSURL *)url
2252 {
2253     String group(groupName);
2254     if (group.isEmpty())
2255         return;
2256     
2257     PageGroup* pageGroup = PageGroup::pageGroup(group);
2258     if (!pageGroup)
2259         return;
2260
2261     pageGroup->removeUserScriptFromWorld(core(world), url);
2262 }
2263
2264 + (void)_removeUserStyleSheetFromGroup:(NSString *)groupName world:(WebScriptWorld *)world url:(NSURL *)url
2265 {
2266     String group(groupName);
2267     if (group.isEmpty())
2268         return;
2269     
2270     PageGroup* pageGroup = PageGroup::pageGroup(group);
2271     if (!pageGroup)
2272         return;
2273
2274     pageGroup->removeUserStyleSheetFromWorld(core(world), url);
2275 }
2276
2277 + (void)_removeUserScriptsFromGroup:(NSString *)groupName world:(WebScriptWorld *)world
2278 {
2279     String group(groupName);
2280     if (group.isEmpty())
2281         return;
2282     
2283     PageGroup* pageGroup = PageGroup::pageGroup(group);
2284     if (!pageGroup)
2285         return;
2286
2287     pageGroup->removeUserScriptsFromWorld(core(world));
2288 }
2289
2290 + (void)_removeUserStyleSheetsFromGroup:(NSString *)groupName world:(WebScriptWorld *)world
2291 {
2292     String group(groupName);
2293     if (group.isEmpty())
2294         return;
2295     
2296     PageGroup* pageGroup = PageGroup::pageGroup(group);
2297     if (!pageGroup)
2298         return;
2299
2300     pageGroup->removeUserStyleSheetsFromWorld(core(world));
2301 }
2302
2303 + (void)_removeAllUserContentFromGroup:(NSString *)groupName
2304 {
2305     String group(groupName);
2306     if (group.isEmpty())
2307         return;
2308     
2309     PageGroup* pageGroup = PageGroup::pageGroup(group);
2310     if (!pageGroup)
2311         return;
2312     
2313     pageGroup->removeAllUserContent();
2314 }
2315
2316 - (BOOL)cssAnimationsSuspended
2317 {
2318     return _private->cssAnimationsSuspended;
2319 }
2320
2321 - (void)setCSSAnimationsSuspended:(BOOL)suspended
2322 {
2323     if (suspended == _private->cssAnimationsSuspended)
2324         return;
2325         
2326     _private->cssAnimationsSuspended = suspended;
2327     
2328     Frame* frame = core([self mainFrame]);
2329     if (suspended)
2330         frame->animation()->suspendAnimations(frame->document());
2331     else
2332         frame->animation()->resumeAnimations(frame->document());
2333 }
2334
2335 @end
2336
2337 @implementation _WebSafeForwarder
2338
2339 // Used to send messages to delegates that implement informal protocols.
2340
2341 - (id)initWithTarget:(id)t defaultTarget:(id)dt catchExceptions:(BOOL)c
2342 {
2343     self = [super init];
2344     if (!self)
2345         return nil;
2346     target = t; // Non retained.
2347     defaultTarget = dt;
2348     catchExceptions = c;
2349     return self;
2350 }
2351
2352 - (void)forwardInvocation:(NSInvocation *)invocation
2353 {
2354     if ([target respondsToSelector:[invocation selector]]) {
2355         if (catchExceptions) {
2356             @try {
2357                 [invocation invokeWithTarget:target];
2358             } @catch(id exception) {
2359                 ReportDiscardedDelegateException([invocation selector], exception);
2360             }
2361         } else
2362             [invocation invokeWithTarget:target];
2363         return;
2364     }
2365
2366     if ([defaultTarget respondsToSelector:[invocation selector]])
2367         [invocation invokeWithTarget:defaultTarget];
2368
2369     // Do nothing quietly if method not implemented.
2370 }
2371
2372 - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
2373 {
2374     return [defaultTarget methodSignatureForSelector:aSelector];
2375 }
2376
2377 @end
2378
2379 @implementation WebView
2380
2381 + (void)initialize
2382 {
2383     static BOOL initialized = NO;
2384     if (initialized)
2385         return;
2386     initialized = YES;
2387
2388     InitWebCoreSystemInterface();
2389
2390     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_applicationWillTerminate) name:NSApplicationWillTerminateNotification object:NSApp];
2391     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:) name:WebPreferencesChangedNotification object:nil];
2392     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesRemovedNotification:) name:WebPreferencesRemovedNotification object:nil];    
2393
2394     continuousSpellCheckingEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebContinuousSpellCheckingEnabled];
2395 #ifndef BUILDING_ON_TIGER
2396     grammarCheckingEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebGrammarCheckingEnabled];
2397 #endif
2398
2399 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
2400     automaticQuoteSubstitutionEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticQuoteSubstitutionEnabled];
2401     automaticLinkDetectionEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticLinkDetectionEnabled];
2402     automaticDashSubstitutionEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticDashSubstitutionEnabled];
2403     automaticTextReplacementEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticTextReplacementEnabled];
2404     automaticSpellingCorrectionEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticSpellingCorrectionEnabled];
2405 #endif
2406 }
2407
2408 + (void)_applicationWillTerminate
2409 {   
2410     applicationIsTerminating = YES;
2411
2412     if (fastDocumentTeardownEnabled())
2413         [self closeAllWebViews];
2414
2415     if (!pluginDatabaseClientCount)
2416         [WebPluginDatabase closeSharedDatabase];
2417
2418     PageGroup::closeLocalStorage();
2419 }
2420
2421 + (BOOL)_canShowMIMEType:(NSString *)MIMEType allowingPlugins:(BOOL)allowPlugins
2422 {
2423     return [self _viewClass:nil andRepresentationClass:nil forMIMEType:MIMEType allowingPlugins:allowPlugins];
2424 }
2425
2426 + (BOOL)canShowMIMEType:(NSString *)MIMEType
2427 {
2428     return [self _canShowMIMEType:MIMEType allowingPlugins:YES];
2429 }
2430
2431 - (BOOL)_canShowMIMEType:(NSString *)MIMEType
2432 {
2433     return [[self class] _canShowMIMEType:MIMEType allowingPlugins:[[[self _webView] preferences] arePlugInsEnabled]];
2434 }
2435
2436 - (WebBasePluginPackage *)_pluginForMIMEType:(NSString *)MIMEType
2437 {
2438     if (![_private->preferences arePlugInsEnabled])
2439         return nil;
2440
2441     WebBasePluginPackage *pluginPackage = [[WebPluginDatabase sharedDatabase] pluginForMIMEType:MIMEType];
2442     if (pluginPackage)
2443         return pluginPackage;
2444     
2445     if (_private->pluginDatabase)
2446         return [_private->pluginDatabase pluginForMIMEType:MIMEType];
2447     
2448     return nil;
2449 }
2450
2451 - (WebBasePluginPackage *)_pluginForExtension:(NSString *)extension
2452 {
2453     if (![_private->preferences arePlugInsEnabled])
2454         return nil;
2455
2456     WebBasePluginPackage *pluginPackage = [[WebPluginDatabase sharedDatabase] pluginForExtension:extension];
2457     if (pluginPackage)
2458         return pluginPackage;
2459     
2460     if (_private->pluginDatabase)
2461         return [_private->pluginDatabase pluginForExtension:extension];
2462     
2463     return nil;
2464 }
2465
2466 - (void)addPluginInstanceView:(NSView *)view
2467 {
2468     if (!_private->pluginDatabase)
2469         _private->pluginDatabase = [[WebPluginDatabase alloc] init];
2470     [_private->pluginDatabase addPluginInstanceView:view];
2471 }
2472
2473 - (void)removePluginInstanceView:(NSView *)view
2474 {
2475     if (_private->pluginDatabase)
2476         [_private->pluginDatabase removePluginInstanceView:view];    
2477 }
2478
2479 - (void)removePluginInstanceViewsFor:(WebFrame*)webFrame 
2480 {
2481     if (_private->pluginDatabase)
2482         [_private->pluginDatabase removePluginInstanceViewsFor:webFrame];    
2483 }
2484
2485 - (BOOL)_isMIMETypeRegisteredAsPlugin:(NSString *)MIMEType
2486 {
2487     if (![_private->preferences arePlugInsEnabled])
2488         return NO;
2489
2490     if ([[WebPluginDatabase sharedDatabase] isMIMETypeRegistered:MIMEType])
2491         return YES;
2492         
2493     if (_private->pluginDatabase && [_private->pluginDatabase isMIMETypeRegistered:MIMEType])
2494         return YES;
2495     
2496     return NO;
2497 }
2498
2499 + (BOOL)canShowMIMETypeAsHTML:(NSString *)MIMEType
2500 {
2501     return [WebFrameView _canShowMIMETypeAsHTML:MIMEType];
2502 }
2503
2504 + (NSArray *)MIMETypesShownAsHTML
2505 {
2506     NSMutableDictionary *viewTypes = [WebFrameView _viewTypesAllowImageTypeOmission:YES];
2507     NSEnumerator *enumerator = [viewTypes keyEnumerator];
2508     id key;
2509     NSMutableArray *array = [[[NSMutableArray alloc] init] autorelease];
2510     
2511     while ((key = [enumerator nextObject])) {
2512         if ([viewTypes objectForKey:key] == [WebHTMLView class])
2513             [array addObject:key];
2514     }
2515     
2516     return array;
2517 }
2518
2519 + (void)setMIMETypesShownAsHTML:(NSArray *)MIMETypes
2520 {
2521     NSDictionary *viewTypes = [[WebFrameView _viewTypesAllowImageTypeOmission:YES] copy];
2522     NSEnumerator *enumerator = [viewTypes keyEnumerator];
2523     id key;
2524     while ((key = [enumerator nextObject])) {
2525         if ([viewTypes objectForKey:key] == [WebHTMLView class])
2526             [WebView _unregisterViewClassAndRepresentationClassForMIMEType:key];
2527     }
2528     
2529     int i, count = [MIMETypes count];
2530     for (i = 0; i < count; i++) {
2531         [WebView registerViewClass:[WebHTMLView class] 
2532                 representationClass:[WebHTMLRepresentation class] 
2533                 forMIMEType:[MIMETypes objectAtIndex:i]];
2534     }
2535     [viewTypes release];
2536 }
2537
2538 + (NSURL *)URLFromPasteboard:(NSPasteboard *)pasteboard
2539 {
2540     return [pasteboard _web_bestURL];
2541 }
2542
2543 + (NSString *)URLTitleFromPasteboard:(NSPasteboard *)pasteboard
2544 {
2545     return [pasteboard stringForType:WebURLNamePboardType];
2546 }
2547
2548 + (void)registerURLSchemeAsLocal:(NSString *)protocol
2549 {
2550     SecurityOrigin::registerURLSchemeAsLocal(protocol);
2551 }
2552
2553 - (id)_initWithArguments:(NSDictionary *) arguments
2554 {
2555     NSCoder *decoder = [arguments objectForKey:@"decoder"];
2556     if (decoder) {
2557         self = [self initWithCoder:decoder];
2558     } else {
2559         ASSERT([arguments objectForKey:@"frame"]);
2560         NSValue *frameValue = [arguments objectForKey:@"frame"];
2561         NSRect frame = (frameValue ? [frameValue rectValue] : NSZeroRect);
2562         NSString *frameName = [arguments objectForKey:@"frameName"];
2563         NSString *groupName = [arguments objectForKey:@"groupName"];
2564         self = [self initWithFrame:frame frameName:frameName groupName:groupName];
2565     }
2566
2567     return self;
2568 }
2569
2570 static bool clientNeedsWebViewInitThreadWorkaround()
2571 {
2572     if (WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_WEBVIEW_INIT_THREAD_WORKAROUND))
2573         return false;
2574
2575     NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
2576
2577     // Installer.
2578     if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.installer"])
2579         return true;
2580
2581     // Automator.
2582     if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.Automator"])
2583         return true;
2584
2585     // Automator Runner.
2586     if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.AutomatorRunner"])
2587         return true;
2588
2589     // Automator workflows.
2590     if ([bundleIdentifier _webkit_hasCaseInsensitivePrefix:@"com.apple.Automator."])
2591         return true;
2592
2593 #if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
2594     // Mail.
2595     if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.Mail"])
2596         return true;
2597 #endif
2598
2599     return false;
2600 }
2601
2602 static bool needsWebViewInitThreadWorkaround()
2603 {
2604     static bool isOldClient = clientNeedsWebViewInitThreadWorkaround();
2605     return isOldClient && !pthread_main_np();
2606 }
2607
2608 - (id)initWithFrame:(NSRect)f
2609 {
2610     return [self initWithFrame:f frameName:nil groupName:nil];
2611 }
2612
2613 - (id)initWithFrame:(NSRect)f frameName:(NSString *)frameName groupName:(NSString *)groupName
2614 {
2615     if (needsWebViewInitThreadWorkaround())
2616         return [[self _webkit_invokeOnMainThread] initWithFrame:f frameName:frameName groupName:groupName];
2617
2618     WebCoreThreadViolationCheckRoundTwo();
2619     return [self _initWithFrame:f frameName:frameName groupName:groupName usesDocumentViews:YES];
2620 }
2621
2622 - (id)initWithCoder:(NSCoder *)decoder
2623 {
2624     if (needsWebViewInitThreadWorkaround())
2625         return [[self _webkit_invokeOnMainThread] initWithCoder:decoder];
2626
2627     WebCoreThreadViolationCheckRoundTwo();
2628     WebView *result = nil;
2629
2630     @try {
2631         NSString *frameName;
2632         NSString *groupName;
2633         WebPreferences *preferences;
2634         BOOL useBackForwardList = NO;
2635         BOOL allowsUndo = YES;
2636         
2637         result = [super initWithCoder:decoder];
2638         result->_private = [[WebViewPrivate alloc] init];
2639
2640         // We don't want any of the archived subviews. The subviews will always
2641         // be created in _commonInitializationFrameName:groupName:.
2642         [[result subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
2643
2644         if ([decoder allowsKeyedCoding]) {
2645             frameName = [decoder decodeObjectForKey:@"FrameName"];
2646             groupName = [decoder decodeObjectForKey:@"GroupName"];
2647             preferences = [decoder decodeObjectForKey:@"Preferences"];
2648             useBackForwardList = [decoder decodeBoolForKey:@"UseBackForwardList"];
2649             if ([decoder containsValueForKey:@"AllowsUndo"])
2650                 allowsUndo = [decoder decodeBoolForKey:@"AllowsUndo"];
2651         } else {
2652             int version;
2653             [decoder decodeValueOfObjCType:@encode(int) at:&version];
2654             frameName = [decoder decodeObject];
2655             groupName = [decoder decodeObject];
2656             preferences = [decoder decodeObject];
2657             if (version > 1)
2658                 [decoder decodeValuesOfObjCTypes:"c", &useBackForwardList];
2659             // The allowsUndo field is no longer written out in encodeWithCoder, but since there are
2660             // version 3 NIBs that have this field encoded, we still need to read it in.
2661             if (version == 3)
2662                 [decoder decodeValuesOfObjCTypes:"c", &allowsUndo];
2663         }
2664
2665         if (![frameName isKindOfClass:[NSString class]])
2666             frameName = nil;
2667         if (![groupName isKindOfClass:[NSString class]])
2668             groupName = nil;
2669         if (![preferences isKindOfClass:[WebPreferences class]])
2670             preferences = nil;
2671
2672         LOG(Encoding, "FrameName = %@, GroupName = %@, useBackForwardList = %d\n", frameName, groupName, (int)useBackForwardList);
2673         [result _commonInitializationWithFrameName:frameName groupName:groupName usesDocumentViews:YES];
2674         [result page]->backForwardList()->setEnabled(useBackForwardList);
2675         result->_private->allowsUndo = allowsUndo;
2676         if (preferences)
2677             [result setPreferences:preferences];
2678     } @catch (NSException *localException) {
2679         result = nil;
2680         [self release];
2681     }
2682
2683     return result;
2684 }
2685
2686 - (void)encodeWithCoder:(NSCoder *)encoder
2687 {
2688     // Set asside the subviews before we archive. We don't want to archive any subviews.
2689     // The subviews will always be created in _commonInitializationFrameName:groupName:.
2690     id originalSubviews = _subviews;
2691     _subviews = nil;
2692
2693     [super encodeWithCoder:encoder];
2694
2695     // Restore the subviews we set aside.
2696     _subviews = originalSubviews;
2697
2698     BOOL useBackForwardList = _private->page && _private->page->backForwardList()->enabled();
2699     if ([encoder allowsKeyedCoding]) {
2700         [encoder encodeObject:[[self mainFrame] name] forKey:@"FrameName"];
2701         [encoder encodeObject:[self groupName] forKey:@"GroupName"];
2702         [encoder encodeObject:[self preferences] forKey:@"Preferences"];
2703         [encoder encodeBool:useBackForwardList forKey:@"UseBackForwardList"];
2704         [encoder encodeBool:_private->allowsUndo forKey:@"AllowsUndo"];
2705     } else {
2706         int version = WebViewVersion;
2707         [encoder encodeValueOfObjCType:@encode(int) at:&version];
2708         [encoder encodeObject:[[self mainFrame] name]];
2709         [encoder encodeObject:[self groupName]];
2710         [encoder encodeObject:[self preferences]];
2711         [encoder encodeValuesOfObjCTypes:"c", &useBackForwardList];
2712         // DO NOT encode any new fields here, doing so will break older WebKit releases.
2713     }
2714
2715     LOG(Encoding, "FrameName = %@, GroupName = %@, useBackForwardList = %d\n", [[self mainFrame] name], [self groupName], (int)useBackForwardList);
2716 }
2717
2718 - (void)dealloc
2719 {
2720     if (WebCoreObjCScheduleDeallocateOnMainThread([WebView class], self))
2721         return;
2722
2723     // call close to ensure we tear-down completely
2724     // this maintains our old behavior for existing applications
2725     [self close];
2726
2727     --WebViewCount;
2728     
2729     if ([self _needsFrameLoadDelegateRetainQuirk])
2730         [_private->frameLoadDelegate release];
2731         
2732     [_private release];
2733     // [super dealloc] can end up dispatching against _private (3466082)
2734     _private = nil;
2735
2736     [super dealloc];
2737 }
2738
2739 - (void)finalize
2740 {
2741     ASSERT(_private->closed);
2742
2743     --WebViewCount;
2744
2745     [super finalize];
2746 }
2747
2748 - (void)close
2749 {
2750     // _close existed first, and some clients might be calling or overriding it, so call through.
2751     [self _close];
2752 }
2753
2754 - (void)setShouldCloseWithWindow:(BOOL)close
2755 {
2756     _private->shouldCloseWithWindow = close;
2757 }
2758
2759 - (BOOL)shouldCloseWithWindow
2760 {
2761     return _private->shouldCloseWithWindow;
2762 }
2763
2764 - (void)addWindowObserversForWindow:(NSWindow *)window
2765 {
2766     if (window) {
2767         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowDidBecomeKey:)
2768             name:NSWindowDidBecomeKeyNotification object:nil];
2769         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowDidResignKey:)
2770             name:NSWindowDidResignKeyNotification object:nil];
2771         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillOrderOnScreen:)
2772             name:WKWindowWillOrderOnScreenNotification() object:window];
2773     }
2774 }
2775
2776 - (void)removeWindowObservers
2777 {
2778     NSWindow *window = [self window];
2779     if (window) {
2780         [[NSNotificationCenter defaultCenter] removeObserver:self
2781             name:NSWindowDidBecomeKeyNotification object:nil];
2782         [[NSNotificationCenter defaultCenter] removeObserver:self
2783             name:NSWindowDidResignKeyNotification object:nil];
2784         [[NSNotificationCenter defaultCenter] removeObserver:self
2785             name:WKWindowWillOrderOnScreenNotification() object:window];
2786     }
2787 }
2788
2789 - (void)viewWillMoveToWindow:(NSWindow *)window
2790 {
2791     // Don't do anything if the WebView isn't initialized.
2792     // This happens when decoding a WebView in a nib.
2793     // FIXME: What sets up the observer of NSWindowWillCloseNotification in this case?
2794     if (!_private || _private->closed)
2795         return;
2796     
2797     if ([self window] && [self window] != [self hostWindow])
2798         [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowWillCloseNotification object:[self window]];
2799
2800     if (window) {
2801         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillClose:) name:NSWindowWillCloseNotification object:window];
2802          
2803         // Ensure that we will receive the events that WebHTMLView (at least) needs.
2804         // The following are expensive enough that we don't want to call them over
2805         // and over, so do them when we move into a window.
2806         [window setAcceptsMouseMovedEvents:YES];
2807         WKSetNSWindowShouldPostEventNotifications(window, YES);
2808     } else
2809         _private->page->willMoveOffscreen();
2810         
2811     if (window != [self window]) {
2812         [self removeWindowObservers];
2813         [self addWindowObserversForWindow:window];
2814     }
2815 }
2816
2817 - (void)viewDidMoveToWindow
2818 {
2819     // Don't do anything if we aren't initialized.  This happens
2820     // when decoding a WebView.  When WebViews are decoded their subviews
2821     // are created by initWithCoder: and so won't be normally
2822     // initialized.  The stub views are discarded by WebView.
2823     if (!_private || _private->closed)
2824         return;
2825
2826     if ([self window])
2827         _private->page->didMoveOnscreen();
2828     
2829     [self _updateActiveState];
2830 }
2831
2832 - (void)_windowDidBecomeKey:(NSNotification *)notification
2833 {
2834     NSWindow *keyWindow = [notification object];
2835     if (keyWindow == [self window] || keyWindow == [[self window] attachedSheet])
2836         [self _updateActiveState];
2837 }
2838
2839 - (void)_windowDidResignKey:(NSNotification *)notification
2840 {
2841     NSWindow *formerKeyWindow = [notification object];
2842     if (formerKeyWindow == [self window] || formerKeyWindow == [[self window] attachedSheet])
2843         [self _updateActiveState];
2844 }
2845
2846 - (void)_windowWillOrderOnScreen:(NSNotification *)notification
2847 {
2848     if (![self shouldUpdateWhileOffscreen])
2849         [self setNeedsDisplay:YES];
2850 }
2851
2852 - (void)_windowWillClose:(NSNotification *)notification
2853 {
2854     if ([self shouldCloseWithWindow] && ([self window] == [self hostWindow] || ([self window] && ![self hostWindow]) || (![self window] && [self hostWindow])))
2855         [self close];
2856 }
2857
2858 - (void)setPreferences:(WebPreferences *)prefs
2859 {
2860     if (!prefs)
2861         prefs = [WebPreferences standardPreferences];
2862
2863     if (_private->preferences == prefs)
2864         return;
2865
2866     [prefs willAddToWebView];
2867
2868     WebPreferences *oldPrefs = _private->preferences;
2869
2870     [[NSNotificationCenter defaultCenter] removeObserver:self name:WebPreferencesChangedNotification object:[self preferences]];
2871     [WebPreferences _removeReferenceForIdentifier:[oldPrefs identifier]];
2872
2873     _private->preferences = [prefs retain];
2874
2875     // After registering for the notification, post it so the WebCore settings update.
2876     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:)
2877         name:WebPreferencesChangedNotification object:[self preferences]];
2878     [[self preferences] _postPreferencesChangesNotification];
2879
2880     [oldPrefs didRemoveFromWebView];
2881     [oldPrefs release];
2882 }
2883
2884 - (WebPreferences *)preferences
2885 {
2886     return _private->preferences;
2887 }
2888
2889 - (void)setPreferencesIdentifier:(NSString *)anIdentifier
2890 {
2891     if (!_private->closed && ![anIdentifier isEqual:[[self preferences] identifier]]) {
2892         WebPreferences *prefs = [[WebPreferences alloc] initWithIdentifier:anIdentifier];
2893         [self setPreferences:prefs];
2894         [prefs release];
2895     }
2896 }
2897
2898 - (NSString *)preferencesIdentifier
2899 {
2900     return [[self preferences] identifier];
2901 }
2902
2903
2904 - (void)setUIDelegate:delegate
2905 {
2906     _private->UIDelegate = delegate;
2907     [_private->UIDelegateForwarder release];
2908     _private->UIDelegateForwarder = nil;
2909 }
2910
2911 - UIDelegate
2912 {
2913     return _private->UIDelegate;
2914 }
2915
2916 - (void)setResourceLoadDelegate: delegate
2917 {
2918     _private->resourceProgressDelegate = delegate;
2919     [self _cacheResourceLoadDelegateImplementations];
2920 }
2921
2922 - resourceLoadDelegate
2923 {
2924     return _private->resourceProgressDelegate;
2925 }
2926
2927 - (void)setDownloadDelegate: delegate
2928 {
2929     _private->downloadDelegate = delegate;
2930 }
2931
2932
2933 - downloadDelegate
2934 {
2935     return _private->downloadDelegate;
2936 }
2937
2938 - (void)setPolicyDelegate:delegate
2939 {
2940     _private->policyDelegate = delegate;
2941     [_private->policyDelegateForwarder release];
2942     _private->policyDelegateForwarder = nil;
2943 }
2944
2945 - policyDelegate
2946 {
2947     return _private->policyDelegate;
2948 }
2949
2950 - (void)setFrameLoadDelegate:delegate
2951 {
2952     // <rdar://problem/6950660> - Due to some subtle WebKit changes - presumably to delegate callback behavior - we've
2953     // unconvered a latent bug in at least one WebKit app where the delegate wasn't properly retained by the app and
2954     // was dealloc'ed before being cleared.
2955     // This is an effort to keep such apps working for now.
2956     if ([self _needsFrameLoadDelegateRetainQuirk]) {
2957         [delegate retain];
2958         [_private->frameLoadDelegate release];
2959     }
2960     
2961     _private->frameLoadDelegate = delegate;
2962     [self _cacheFrameLoadDelegateImplementations];
2963
2964 #if ENABLE(ICONDATABASE)
2965     // If this delegate wants callbacks for icons, fire up the icon database.
2966     if (_private->frameLoadDelegateImplementations.didReceiveIconForFrameFunc)
2967         [WebIconDatabase sharedIconDatabase];
2968 #endif
2969 }
2970
2971 - frameLoadDelegate
2972 {
2973     return _private->frameLoadDelegate;
2974 }
2975
2976 - (WebFrame *)mainFrame
2977 {
2978     // This can be called in initialization, before _private has been set up (3465613)
2979     if (!_private || !_private->page)
2980         return nil;
2981     return kit(_private->page->mainFrame());
2982 }
2983
2984 - (WebFrame *)selectedFrame
2985 {
2986     if (_private->usesDocumentViews) {
2987         // If the first responder is a view in our tree, we get the frame containing the first responder.
2988         // This is faster than searching the frame hierarchy, and will give us a result even in the case
2989         // where the focused frame doesn't actually contain a selection.
2990         WebFrame *focusedFrame = [self _focusedFrame];
2991         if (focusedFrame)
2992             return focusedFrame;
2993     }
2994     
2995     // If the first responder is outside of our view tree, we search for a frame containing a selection.
2996     // There should be at most only one of these.
2997     return [[self mainFrame] _findFrameWithSelection];
2998 }
2999
3000 - (WebBackForwardList *)backForwardList
3001 {
3002     if (!_private->page)
3003         return nil;
3004     if (!_private->page->backForwardList()->enabled())
3005         return nil;
3006     return kit(_private->page->backForwardList());
3007 }
3008
3009 - (void)setMaintainsBackForwardList:(BOOL)flag
3010 {
3011     if (!_private->page)
3012         return;
3013     _private->page->backForwardList()->setEnabled(flag);
3014 }
3015
3016 - (BOOL)goBack
3017 {
3018     if (!_private->page)
3019         return NO;
3020     
3021     return _private->page->goBack();
3022 }
3023
3024 - (BOOL)goForward
3025 {
3026     if (!_private->page)
3027         return NO;
3028
3029     return _private->page->goForward();
3030 }
3031
3032 - (BOOL)goToBackForwardItem:(WebHistoryItem *)item
3033 {
3034     if (!_private->page)
3035         return NO;
3036
3037     _private->page->goToItem(core(item), FrameLoadTypeIndexedBackForward);
3038     return YES;
3039 }
3040
3041 - (void)setTextSizeMultiplier:(float)m
3042 {
3043     [self _setZoomMultiplier:m isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3044 }
3045
3046 - (float)textSizeMultiplier
3047 {
3048     return [self _realZoomMultiplierIsTextOnly] ? _private->zoomMultiplier : 1.0f;
3049 }
3050
3051 - (void)_setZoomMultiplier:(float)m isTextOnly:(BOOL)isTextOnly
3052 {
3053     // NOTE: This has no visible effect when viewing a PDF (see <rdar://problem/4737380>)
3054     _private->zoomMultiplier = m;
3055     ASSERT(_private->page);
3056     if (_private->page)
3057         _private->page->settings()->setZoomsTextOnly(isTextOnly);
3058     
3059     // FIXME: it would be nice to rework this code so that _private->zoomMultiplier doesn't exist and callers
3060     // all access _private->page->settings().
3061     Frame* coreFrame = [self _mainCoreFrame];
3062     if (coreFrame)
3063         coreFrame->setZoomFactor(m, isTextOnly);
3064 }
3065
3066 - (float)_zoomMultiplier:(BOOL)isTextOnly
3067 {
3068     if (isTextOnly != [self _realZoomMultiplierIsTextOnly])
3069         return 1.0f;
3070     return _private->zoomMultiplier;
3071 }
3072
3073 - (float)_realZoomMultiplier
3074 {
3075     return _private->zoomMultiplier;
3076 }
3077
3078 - (BOOL)_realZoomMultiplierIsTextOnly
3079 {
3080     if (!_private->page)
3081         return NO;
3082     
3083     return _private->page->settings()->zoomsTextOnly();
3084 }
3085
3086 #define MinimumZoomMultiplier       0.5f
3087 #define MaximumZoomMultiplier       3.0f
3088 #define ZoomMultiplierRatio         1.2f
3089
3090 - (BOOL)_canZoomOut:(BOOL)isTextOnly
3091 {
3092     id docView = [[[self mainFrame] frameView] documentView];
3093     if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
3094         id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
3095         return [zoomingDocView _canZoomOut];
3096     }
3097     return [self _zoomMultiplier:isTextOnly] / ZoomMultiplierRatio > MinimumZoomMultiplier;
3098 }
3099
3100
3101 - (BOOL)_canZoomIn:(BOOL)isTextOnly
3102 {
3103     id docView = [[[self mainFrame] frameView] documentView];
3104     if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
3105         id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
3106         return [zoomingDocView _canZoomIn];
3107     }
3108     return [self _zoomMultiplier:isTextOnly] * ZoomMultiplierRatio < MaximumZoomMultiplier;
3109 }
3110
3111 - (IBAction)_zoomOut:(id)sender isTextOnly:(BOOL)isTextOnly
3112 {
3113     id docView = [[[self mainFrame] frameView] documentView];
3114     if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
3115         id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
3116         return [zoomingDocView _zoomOut:sender];
3117     }
3118     float newScale = [self _zoomMultiplier:isTextOnly] / ZoomMultiplierRatio;
3119     if (newScale > MinimumZoomMultiplier)
3120         [self _setZoomMultiplier:newScale isTextOnly:isTextOnly];
3121 }
3122
3123 - (IBAction)_zoomIn:(id)sender isTextOnly:(BOOL)isTextOnly
3124 {
3125     id docView = [[[self mainFrame] frameView] documentView];
3126     if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
3127         id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
3128         return [zoomingDocView _zoomIn:sender];
3129     }
3130     float newScale = [self _zoomMultiplier:isTextOnly] * ZoomMultiplierRatio;
3131     if (newScale < MaximumZoomMultiplier)
3132         [self _setZoomMultiplier:newScale isTextOnly:isTextOnly];
3133 }
3134
3135 - (BOOL)_canResetZoom:(BOOL)isTextOnly
3136 {
3137     id docView = [[[self mainFrame] frameView] documentView];
3138     if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
3139         id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
3140         return [zoomingDocView _canResetZoom];
3141     }
3142     return [self _zoomMultiplier:isTextOnly] != 1.0f;
3143 }
3144
3145 - (IBAction)_resetZoom:(id)sender isTextOnly:(BOOL)isTextOnly
3146 {
3147     id docView = [[[self mainFrame] frameView] documentView];
3148     if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
3149         id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
3150         return [zoomingDocView _resetZoom:sender];
3151     }
3152     if ([self _zoomMultiplier:isTextOnly] != 1.0f)
3153         [self _setZoomMultiplier:1.0f isTextOnly:isTextOnly];
3154 }
3155
3156 - (void)setApplicationNameForUserAgent:(NSString *)applicationName
3157 {
3158     NSString *name = [applicationName copy];
3159     [_private->applicationNameForUserAgent release];
3160     _private->applicationNameForUserAgent = name;
3161     if (!_private->userAgentOverridden)
3162         _private->userAgent = String();
3163 }
3164
3165 - (NSString *)applicationNameForUserAgent
3166 {
3167     return [[_private->applicationNameForUserAgent retain] autorelease];
3168 }
3169
3170 - (void)setCustomUserAgent:(NSString *)userAgentString
3171 {
3172     _private->userAgent = userAgentString;
3173     _private->userAgentOverridden = userAgentString != nil;
3174 }
3175
3176 - (NSString *)customUserAgent
3177 {
3178     if (!_private->userAgentOverridden)
3179         return nil;
3180     return _private->userAgent;
3181 }
3182
3183 - (void)setMediaStyle:(NSString *)mediaStyle
3184 {
3185     if (_private->mediaStyle != mediaStyle) {
3186         [_private->mediaStyle release];
3187         _private->mediaStyle = [mediaStyle copy];
3188     }
3189 }
3190
3191 - (NSString *)mediaStyle
3192 {
3193     return _private->mediaStyle;
3194 }
3195
3196 - (BOOL)supportsTextEncoding
3197 {
3198     id documentView = [[[self mainFrame] frameView] documentView];
3199     return [documentView conformsToProtocol:@protocol(WebDocumentText)]
3200         && [documentView supportsTextEncoding];
3201 }
3202
3203 - (void)setCustomTextEncodingName:(NSString *)encoding
3204 {
3205     NSString *oldEncoding = [self customTextEncodingName];
3206     if (encoding == oldEncoding || [encoding isEqualToString:oldEncoding])
3207         return;
3208     if (Frame* mainFrame = [self _mainCoreFrame])
3209         mainFrame->loader()->reloadWithOverrideEncoding(encoding);
3210 }
3211
3212 - (NSString *)_mainFrameOverrideEncoding
3213 {
3214     WebDataSource *dataSource = [[self mainFrame] provisionalDataSource];
3215     if (dataSource == nil)
3216         dataSource = [[self mainFrame] _dataSource];
3217     if (dataSource == nil)
3218         return nil;
3219     return nsStringNilIfEmpty([dataSource _documentLoader]->overrideEncoding());
3220 }
3221
3222 - (NSString *)customTextEncodingName
3223 {
3224     return [self _mainFrameOverrideEncoding];
3225 }
3226
3227 - (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script
3228 {
3229     // Return statements are only valid in a function but some applications pass in scripts
3230     // prefixed with return (<rdar://problems/5103720&4616860>) since older WebKit versions
3231     // silently ignored the return. If the application is linked against an earlier version
3232     // of WebKit we will strip the return so the script wont fail.
3233     if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_JAVASCRIPT_RETURN_QUIRK)) {
3234         NSRange returnStringRange = [script rangeOfString:@"return "];
3235         if (returnStringRange.length && !returnStringRange.location)
3236             script = [script substringFromIndex:returnStringRange.location + returnStringRange.length];
3237     }
3238
3239     NSString *result = [[self mainFrame] _stringByEvaluatingJavaScriptFromString:script];
3240     // The only way stringByEvaluatingJavaScriptFromString can return nil is if the frame was removed by the script
3241     // Since there's no way to get rid of the main frame, result will never ever be nil here.
3242     ASSERT(result);
3243
3244     return result;
3245 }
3246
3247 - (WebScriptObject *)windowScriptObject
3248 {
3249     Frame* coreFrame = [self _mainCoreFrame];
3250     if (!coreFrame)
3251         return nil;
3252     return coreFrame->script()->windowScriptObject();
3253 }
3254
3255 // Get the appropriate user-agent string for a particular URL.
3256 - (NSString *)userAgentForURL:(NSURL *)url
3257 {
3258     if (_private->useSiteSpecificSpoofing) {
3259         // No current site-specific spoofs.
3260     }
3261
3262     if (_private->userAgent.isNull())
3263         _private->userAgent = [[self class] _standardUserAgentWithApplicationName:_private->applicationNameForUserAgent];
3264
3265     return _private->userAgent;
3266 }
3267
3268 - (void)setHostWindow:(NSWindow *)hostWindow
3269 {
3270     if (_private->closed)
3271         return;
3272     if (hostWindow == _private->hostWindow)
3273         return;
3274
3275     Frame* coreFrame = [self _mainCoreFrame];
3276     if (_private->usesDocumentViews) {
3277         for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
3278             [[[kit(frame) frameView] documentView] viewWillMoveToHostWindow:hostWindow];
3279     }
3280     if (_private->hostWindow && [self window] != _private->hostWindow)
3281         [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowWillCloseNotification object:_private->hostWindow];
3282     if (hostWindow)
3283         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillClose:) name:NSWindowWillCloseNotification object:hostWindow];
3284     [_private->hostWindow release];
3285     _private->hostWindow = [hostWindow retain];
3286     if (_private->usesDocumentViews) {
3287         for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
3288             [[[kit(frame) frameView] documentView] viewDidMoveToHostWindow];
3289     }
3290 }
3291
3292 - (NSWindow *)hostWindow
3293 {
3294     // -[WebView hostWindow] can sometimes be called from the WebView's [super dealloc] method
3295     // so we check here to make sure it's not null.
3296     if (!_private)
3297         return nil;
3298     
3299     return _private->hostWindow;
3300 }
3301
3302 - (NSView <WebDocumentView> *)documentViewAtWindowPoint:(NSPoint)point
3303 {
3304     return [[self _frameViewAtWindowPoint:point] documentView];
3305 }
3306
3307 - (NSDictionary *)_elementAtWindowPoint:(NSPoint)windowPoint
3308 {
3309     WebFrameView *frameView = [self _frameViewAtWindowPoint:windowPoint];
3310     if (!frameView)
3311         return nil;
3312     NSView <WebDocumentView> *documentView = [frameView documentView];
3313     if ([documentView conformsToProtocol:@protocol(WebDocumentElement)]) {
3314         NSPoint point = [documentView convertPoint:windowPoint fromView:nil];
3315         return [(NSView <WebDocumentElement> *)documentView elementAtPoint:point];
3316     }
3317     return [NSDictionary dictionaryWithObject:[frameView webFrame] forKey:WebElementFrameKey];
3318 }
3319
3320 - (NSDictionary *)elementAtPoint:(NSPoint)point
3321 {
3322     return [self _elementAtWindowPoint:[self convertPoint:point toView:nil]];
3323 }
3324
3325 // The following 2 internal NSView methods are called on the drag destination to make scrolling while dragging work.
3326 // Scrolling while dragging will only work if the drag destination is in a scroll view. The WebView is the drag destination. 
3327 // When dragging to a WebView, the document subview should scroll, but it doesn't because it is not the drag destination. 
3328 // Forward these calls to the document subview to make its scroll view scroll.
3329 - (void)_autoscrollForDraggingInfo:(id)draggingInfo timeDelta:(NSTimeInterval)repeatDelta
3330 {
3331     NSView <WebDocumentView> *documentView = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3332     [documentView _autoscrollForDraggingInfo:draggingInfo timeDelta:repeatDelta];
3333 }
3334
3335 - (BOOL)_shouldAutoscrollForDraggingInfo:(id)draggingInfo
3336 {
3337     NSView <WebDocumentView> *documentView = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3338     return [documentView _shouldAutoscrollForDraggingInfo:draggingInfo];
3339 }
3340
3341 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)draggingInfo
3342 {
3343     NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3344     WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]] ? (WebHTMLView*)view : nil);
3345     IntPoint client([draggingInfo draggingLocation]);
3346     IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
3347     DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
3348     return core(self)->dragController()->dragEntered(&dragData);
3349 }
3350
3351 - (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)draggingInfo
3352 {
3353     Page* page = core(self);
3354     if (!page)
3355         return NSDragOperationNone;
3356
3357     NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3358     WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]] ? (WebHTMLView*)view : nil);
3359     IntPoint client([draggingInfo draggingLocation]);
3360     IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
3361     DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
3362     return page->dragController()->dragUpdated(&dragData);
3363 }
3364
3365 - (void)draggingExited:(id <NSDraggingInfo>)draggingInfo
3366 {
3367     Page* page = core(self);
3368     if (!page)
3369         return;
3370
3371     NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3372     WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]] ? (WebHTMLView*)view : nil);
3373     IntPoint client([draggingInfo draggingLocation]);
3374     IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
3375     DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
3376     page->dragController()->dragExited(&dragData);
3377 }
3378
3379 - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)draggingInfo
3380 {
3381     return YES;
3382 }
3383
3384 - (BOOL)performDragOperation:(id <NSDraggingInfo>)draggingInfo
3385 {
3386     NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3387     WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]]? (WebHTMLView*)view : nil);
3388     IntPoint client([draggingInfo draggingLocation]);
3389     IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
3390     DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
3391     return core(self)->dragController()->performDrag(&dragData);
3392 }
3393
3394 - (NSView *)_hitTest:(NSPoint *)point dragTypes:(NSSet *)types
3395 {
3396     NSView *hitView = [super _hitTest:point dragTypes:types];
3397     if (!hitView && [[self superview] mouse:*point inRect:[self frame]])
3398         return self;
3399     return hitView;
3400 }
3401
3402 - (BOOL)acceptsFirstResponder
3403 {
3404     if (_private->usesDocumentViews)
3405         return [[[self mainFrame] frameView] acceptsFirstResponder];
3406
3407     // FIXME (Viewless): Need more code from WebHTMLView here.
3408     return YES;
3409 }
3410
3411 - (BOOL)becomeFirstResponder
3412 {
3413     if (_private->usesDocumentViews) {
3414         if (_private->becomingFirstResponder) {
3415             // Fix for unrepro infinite recursion reported in Radar 4448181. If we hit this assert on
3416             // a debug build, we should figure out what causes the problem and do a better fix.
3417             ASSERT_NOT_REACHED();
3418             return NO;
3419         }
3420         
3421         // This works together with setNextKeyView to splice the WebView into
3422         // the key loop similar to the way NSScrollView does this. Note that
3423         // WebFrameView has very similar code.
3424         NSWindow *window = [self window];
3425         WebFrameView *mainFrameView = [[self mainFrame] frameView];
3426
3427         NSResponder *previousFirstResponder = [[self window] _oldFirstResponderBeforeBecoming];
3428         BOOL fromOutside = ![previousFirstResponder isKindOfClass:[NSView class]] || (![(NSView *)previousFirstResponder isDescendantOf:self] && previousFirstResponder != self);
3429
3430         if ([window keyViewSelectionDirection] == NSSelectingPrevious) {
3431             NSView *previousValidKeyView = [self previousValidKeyView];
3432             if (previousValidKeyView != self && previousValidKeyView != mainFrameView) {
3433                 _private->becomingFirstResponder = YES;
3434                 _private->becomingFirstResponderFromOutside = fromOutside;
3435                 [window makeFirstResponder:previousValidKeyView];
3436                 _private->becomingFirstResponderFromOutside = NO;
3437                 _private->becomingFirstResponder = NO;
3438                 return YES;
3439             }
3440             return NO;
3441         }
3442
3443         if ([mainFrameView acceptsFirstResponder]) {
3444             _private->becomingFirstResponder = YES;
3445             _private->becomingFirstResponderFromOutside = fromOutside;
3446             [window makeFirstResponder:mainFrameView];
3447             _private->becomingFirstResponderFromOutside = NO;
3448             _private->becomingFirstResponder = NO;
3449             return YES;
3450         } 
3451
3452         return NO;
3453     }
3454
3455     // FIXME (Viewless): Need more code from WebHTMLView here.
3456     return YES;
3457 }
3458
3459 - (NSView *)_webcore_effectiveFirstResponder
3460 {
3461     if (_private && _private->usesDocumentViews) {
3462         if (WebFrameView *frameView = [[self mainFrame] frameView])
3463             return [frameView _webcore_effectiveFirstResponder];
3464     }
3465     return [super _webcore_effectiveFirstResponder];
3466 }
3467
3468 - (void)setNextKeyView:(NSView *)view
3469 {
3470     if (_private && _private->usesDocumentViews) {
3471         // This works together with becomeFirstResponder to splice the WebView into
3472         // the key loop similar to the way NSScrollView does this. Note that
3473         // WebFrameView has similar code.
3474         if (WebFrameView *mainFrameView = [[self mainFrame] frameView]) {
3475             [mainFrameView setNextKeyView:view];
3476             return;
3477         }
3478     }
3479
3480     [super setNextKeyView:view];
3481 }
3482
3483 static WebFrame *incrementFrame(WebFrame *frame, BOOL forward, BOOL wrapFlag)
3484 {
3485     Frame* coreFrame = core(frame);
3486     return kit(forward
3487         ? coreFrame->tree()->traverseNextWithWrap(wrapFlag)
3488         : coreFrame->tree()->traversePreviousWithWrap(wrapFlag));
3489 }
3490
3491 - (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag
3492 {
3493     return [self searchFor:string direction:forward caseSensitive:caseFlag wrap:wrapFlag startInSelection:NO];
3494 }
3495
3496 + (void)registerViewClass:(Class)viewClass representationClass:(Class)representationClass forMIMEType:(NSString *)MIMEType
3497 {
3498     [[WebFrameView _viewTypesAllowImageTypeOmission:YES] setObject:viewClass forKey:MIMEType];
3499     [[WebDataSource _repTypesAllowImageTypeOmission:YES] setObject:representationClass forKey:MIMEType];
3500     
3501     // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
3502     // in the WebCore MIMEType registry.  For now we're doing this in a safe, limited manner
3503     // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
3504     if ([viewClass class] == [WebHTMLView class])
3505         MIMETypeRegistry::getSupportedNonImageMIMETypes().add(MIMEType);
3506 }
3507
3508 - (void)setGroupName:(NSString *)groupName
3509 {
3510     if (!_private->page)
3511         return;
3512     _private->page->setGroupName(groupName);
3513 }
3514
3515 - (NSString *)groupName
3516 {
3517     if (!_private->page)
3518         return nil;
3519     return _private->page->groupName();
3520 }
3521
3522 - (double)estimatedProgress
3523 {
3524     if (!_private->page)
3525         return 0.0;
3526     return _private->page->progress()->estimatedProgress();
3527 }
3528
3529 - (NSArray *)pasteboardTypesForSelection
3530 {
3531     NSView <WebDocumentView> *documentView = [[[self _selectedOrMainFrame] frameView] documentView];
3532     if ([documentView conformsToProtocol:@protocol(WebDocumentSelection)]) {
3533         return [(NSView <WebDocumentSelection> *)documentView pasteboardTypesForSelection];
3534     }
3535     return [NSArray array];
3536 }
3537
3538 - (void)writeSelectionWithPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
3539 {
3540     WebFrame *frame = [self _selectedOrMainFrame];
3541     if (frame && [frame _hasSelection]) {
3542         NSView <WebDocumentView> *documentView = [[frame frameView] documentView];
3543         if ([documentView conformsToProtocol:@protocol(WebDocumentSelection)])
3544             [(NSView <WebDocumentSelection> *)documentView writeSelectionWithPasteboardTypes:types toPasteboard:pasteboard];
3545     }
3546 }
3547
3548 - (NSArray *)pasteboardTypesForElement:(NSDictionary *)element
3549 {
3550     if ([element objectForKey:WebElementImageURLKey] != nil) {
3551         return [NSPasteboard _web_writableTypesForImageIncludingArchive:([element objectForKey:WebElementDOMNodeKey] != nil)];
3552     } else if ([element objectForKey:WebElementLinkURLKey] != nil) {
3553         return [NSPasteboard _web_writableTypesForURL];
3554     } else if ([[element objectForKey:WebElementIsSelectedKey] boolValue]) {
3555         return [self pasteboardTypesForSelection];
3556     }
3557     return [NSArray array];
3558 }
3559
3560 - (void)writeElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
3561 {
3562     if ([element objectForKey:WebElementImageURLKey] != nil) {
3563         [self _writeImageForElement:element withPasteboardTypes:types toPasteboard:pasteboard];
3564     } else if ([element objectForKey:WebElementLinkURLKey] != nil) {
3565         [self _writeLinkElement:element withPasteboardTypes:types toPasteboard:pasteboard];
3566     } else if ([[element objectForKey:WebElementIsSelectedKey] boolValue]) {
3567         [self writeSelectionWithPasteboardTypes:types toPasteboard:pasteboard];
3568     }
3569 }
3570
3571 - (void)moveDragCaretToPoint:(NSPoint)point
3572 {
3573     if (Page* page = core(self))
3574         page->dragController()->placeDragCaret(IntPoint([self convertPoint:point toView:nil]));
3575 }
3576
3577 - (void)removeDragCaret
3578 {
3579     if (Page* page = core(self))
3580         page->dragController()->dragEnded();
3581 }
3582
3583 - (void)setMainFrameURL:(NSString *)URLString
3584 {
3585     [[self mainFrame] loadRequest: [NSURLRequest requestWithURL: [NSURL _web_URLWithDataAsString: URLString]]];
3586 }
3587
3588 - (NSString *)mainFrameURL
3589 {
3590     WebDataSource *ds;
3591     ds = [[self mainFrame] provisionalDataSource];
3592     if (!ds)
3593         ds = [[self mainFrame] _dataSource];
3594     return [[[ds request] URL] _web_originalDataAsString];
3595 }
3596
3597 - (BOOL)isLoading
3598 {
3599     LOG (Bindings, "isLoading = %d", (int)[self _isLoading]);
3600     return [self _isLoading];
3601 }
3602
3603 - (NSString *)mainFrameTitle
3604 {
3605     NSString *mainFrameTitle = [[[self mainFrame] _dataSource] pageTitle];
3606     return (mainFrameTitle != nil) ? mainFrameTitle : (NSString *)@"";
3607 }
3608
3609 - (NSImage *)mainFrameIcon
3610 {
3611     return [[WebIconDatabase sharedIconDatabase] iconForURL:[[[[self mainFrame] _dataSource] _URL] _web_originalDataAsString] withSize:WebIconSmallSize];
3612 }
3613
3614 - (DOMDocument *)mainFrameDocument
3615 {
3616     // only return the actual value if the state we're in gives NSTreeController
3617     // enough time to release its observers on the old model
3618     if (_private->mainFrameDocumentReady)
3619         return [[self mainFrame] DOMDocument];
3620     return nil;
3621 }
3622
3623 - (void)setDrawsBackground:(BOOL)drawsBackground
3624 {
3625     if (_private->drawsBackground == drawsBackground)
3626         return;
3627     _private->drawsBackground = drawsBackground;
3628     [[self mainFrame] _updateBackgroundAndUpdatesWhileOffscreen];
3629 }
3630
3631 - (BOOL)drawsBackground
3632 {
3633     // This method can be called beneath -[NSView dealloc] after we have cleared _private,
3634     // indirectly via -[WebFrameView viewDidMoveToWindow].
3635     return !_private || _private->drawsBackground;
3636 }
3637
3638 - (void)setShouldUpdateWhileOffscreen:(BOOL)updateWhileOffscreen
3639 {
3640     if (_private->shouldUpdateWhileOffscreen == updateWhileOffscreen)
3641         return;
3642     _private->shouldUpdateWhileOffscreen = updateWhileOffscreen;
3643     [[self mainFrame] _updateBackgroundAndUpdatesWhileOffscreen];
3644 }
3645
3646 - (BOOL)shouldUpdateWhileOffscreen
3647 {
3648     return _private->shouldUpdateWhileOffscreen;
3649 }
3650
3651 - (void)setCurrentNodeHighlight:(WebNodeHighlight *)nodeHighlight
3652 {
3653     id old = _private->currentNodeHighlight;
3654     _private->currentNodeHighlight = [nodeHighlight retain];
3655     [old release];
3656 }
3657
3658 - (WebNodeHighlight *)currentNodeHighlight
3659 {
3660     return _private->currentNodeHighlight;
3661 }
3662
3663 - (NSView *)previousValidKeyView
3664 {
3665     NSView *result = [super previousValidKeyView];
3666
3667     // Work around AppKit bug 6905484. If the result is a view that's inside this one, it's
3668     // possible it is the wrong answer, because the fact that it's a descendant causes the
3669     // code that implements key view redirection to fail; this means we won't redirect to
3670     // the toolbar, for example, when we hit the edge of a window. Since the bug is specific
3671     // to cases where the receiver of previousValidKeyView is an ancestor of the last valid
3672     // key view in the loop, we can sidestep it by walking along previous key views until
3673     // we find one that is not a superview, then using that to call previousValidKeyView.
3674
3675     if (![result isDescendantOf:self])
3676         return result;
3677
3678     // Use a visited set so we don't loop indefinitely when walking crazy key loops.
3679     // AppKit uses such sets internally and we want our loop to be as robust as its loops.
3680     RetainPtr<CFMutableSetRef> visitedViews = CFSetCreateMutable(0, 0, 0);
3681     CFSetAddValue(visitedViews.get(), result);
3682
3683     NSView *previousView = self;
3684     do {
3685         CFSetAddValue(visitedViews.get(), previousView);
3686         previousView = [previousView previousKeyView];
3687         if (!previousView || CFSetGetValue(visitedViews.get(), previousView))
3688             return result;
3689     } while ([result isDescendantOf:previousView]);
3690     return [previousView previousValidKeyView];
3691 }
3692
3693 @end
3694
3695 @implementation WebView (WebIBActions)
3696
3697 - (IBAction)takeStringURLFrom: sender
3698 {
3699     NSString *URLString = [sender stringValue];
3700     
3701     [[self mainFrame] loadRequest: [NSURLRequest requestWithURL: [NSURL _web_URLWithDataAsString: URLString]]];
3702 }
3703
3704 - (BOOL)canGoBack
3705 {
3706     if (!_private->page)
3707         return NO;
3708
3709     return !!_private->page->backForwardList()->backItem();
3710 }
3711
3712 - (BOOL)canGoForward
3713 {
3714     if (!_private->page)
3715         return NO;
3716
3717     return !!_private->page->backForwardList()->forwardItem();
3718 }
3719
3720 - (IBAction)goBack:(id)sender
3721 {
3722     [self goBack];
3723 }
3724
3725 - (IBAction)goForward:(id)sender
3726 {
3727     [self goForward];
3728 }
3729
3730 - (IBAction)stopLoading:(id)sender
3731 {
3732     [[self mainFrame] stopLoading];
3733 }
3734
3735 - (IBAction)reload:(id)sender
3736 {
3737     [[self mainFrame] reload];
3738 }
3739
3740 - (IBAction)reloadFromOrigin:(id)sender
3741 {
3742     [[self mainFrame] reloadFromOrigin];
3743 }
3744
3745 // FIXME: This code should move into WebCore so that it is not duplicated in each WebKit.
3746 // (This includes canMakeTextSmaller/Larger, makeTextSmaller/Larger, and canMakeTextStandardSize/makeTextStandardSize)
3747 - (BOOL)canMakeTextSmaller
3748 {
3749     return [self _canZoomOut:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3750 }
3751
3752 - (IBAction)makeTextSmaller:(id)sender
3753 {
3754     return [self _zoomOut:sender isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3755 }
3756
3757 - (BOOL)canMakeTextLarger
3758 {
3759     return [self _canZoomIn:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3760 }
3761
3762 - (IBAction)makeTextLarger:(id)sender
3763 {
3764     return [self _zoomIn:sender isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3765 }
3766
3767 - (BOOL)canMakeTextStandardSize
3768 {
3769     return [self _canResetZoom:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3770 }
3771
3772 - (IBAction)makeTextStandardSize:(id)sender
3773 {
3774    return [self _resetZoom:sender isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3775 }
3776
3777 - (IBAction)toggleSmartInsertDelete:(id)sender
3778 {
3779     [self setSmartInsertDeleteEnabled:![self smartInsertDeleteEnabled]];
3780 }
3781
3782 - (IBAction)toggleContinuousSpellChecking:(id)sender
3783 {
3784     [self setContinuousSpellCheckingEnabled:![self isContinuousSpellCheckingEnabled]];
3785 }
3786
3787 - (BOOL)_responderValidateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item
3788 {
3789     id responder = [self _responderForResponderOperations];
3790     if (responder != self && [responder respondsToSelector:[item action]]) {
3791         if ([responder respondsToSelector:@selector(validateUserInterfaceItemWithoutDelegate:)])
3792             return [responder validateUserInterfaceItemWithoutDelegate:item];
3793         if ([responder respondsToSelector:@selector(validateUserInterfaceItem:)])
3794             return [responder validateUserInterfaceItem:item];
3795         return YES;
3796     }
3797     return NO;
3798 }
3799
3800 #define VALIDATE(name) \
3801     else if (action == @selector(name:)) { return [self _responderValidateUserInterfaceItem:item]; }
3802
3803 - (BOOL)validateUserInterfaceItemWithoutDelegate:(id <NSValidatedUserInterfaceItem>)item
3804 {
3805     SEL action = [item action];
3806
3807     if (action == @selector(goBack:)) {
3808         return [self canGoBack];
3809     } else if (action == @selector(goForward:)) {
3810         return [self canGoForward];
3811     } else if (action == @selector(makeTextLarger:)) {
3812         return [self canMakeTextLarger];
3813     } else if (action == @selector(makeTextSmaller:)) {
3814         return [self canMakeTextSmaller];
3815     } else if (action == @selector(makeTextStandardSize:)) {
3816         return [self canMakeTextStandardSize];
3817     } else if (action == @selector(reload:)) {
3818         return [[self mainFrame] _dataSource] != nil;
3819     } else if (action == @selector(stopLoading:)) {
3820         return [self _isLoading];
3821     } else if (action == @selector(toggleContinuousSpellChecking:)) {
3822         BOOL checkMark = NO;
3823         BOOL retVal = NO;
3824         if ([self _continuousCheckingAllowed]) {
3825             checkMark = [self isContinuousSpellCheckingEnabled];
3826             retVal = YES;
3827         }
3828         if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
3829             NSMenuItem *menuItem = (NSMenuItem *)item;
3830             [menuItem setState:checkMark ? NSOnState : NSOffState];
3831         }
3832         return retVal;
3833     } else if (action == @selector(toggleSmartInsertDelete:)) {
3834         BOOL checkMark = [self smartInsertDeleteEnabled];
3835         if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
3836             NSMenuItem *menuItem = (NSMenuItem *)item;
3837             [menuItem setState:checkMark ? NSOnState : NSOffState];
3838         }
3839         return YES;
3840 #ifndef BUILDING_ON_TIGER
3841     } else if (action == @selector(toggleGrammarChecking:)) {
3842         BOOL checkMark = [self isGrammarCheckingEnabled];
3843         if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
3844             NSMenuItem *menuItem = (NSMenuItem *)item;
3845             [menuItem setState:checkMark ? NSOnState : NSOffState];
3846         }
3847         return YES;
3848 #endif
3849 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
3850     } else if (action == @selector(toggleAutomaticQuoteSubstitution:)) {
3851         BOOL checkMark = [self isAutomaticQuoteSubstitutionEnabled];
3852         if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
3853             NSMenuItem *menuItem = (NSMenuItem *)item;
3854             [menuItem setState:checkMark ? NSOnState : NSOffState];
3855         }
3856         return YES;
3857     } else if (action == @selector(toggleAutomaticLinkDetection:)) {
3858         BOOL checkMark = [self isAutomaticLinkDetectionEnabled];
3859         if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
3860             NSMenuItem *menuItem = (NSMenuItem *)item;
3861             [menuItem setState:checkMark ? NSOnState : NSOffState];
3862         }
3863         return YES;
3864     } else if (action == @selector(toggleAutomaticDashSubstitution:)) {
3865         BOOL checkMark = [self isAutomaticDashSubstitutionEnabled];
3866         if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
3867             NSMenuItem *menuItem = (NSMenuItem *)item;
3868             [menuItem setState:checkMark ? NSOnState : NSOffState];
3869         }
3870         return YES;
3871     } else if (action == @selector(toggleAutomaticTextReplacement:)) {
3872         BOOL checkMark = [self isAutomaticTextReplacementEnabled];
3873         if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
3874             NSMenuItem *menuItem = (NSMenuItem *)item;
3875             [menuItem setState:checkMark ? NSOnState : NSOffState];
3876         }
3877         return YES;
3878     } else if (action == @selector(toggleAutomaticSpellingCorrection:)) {
3879         BOOL checkMark = [self isAutomaticSpellingCorrectionEnabled];
3880         if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
3881             NSMenuItem *menuItem = (NSMenuItem *)item;
3882             [menuItem setState:checkMark ? NSOnState : NSOffState];
3883         }
3884         return YES;
3885 #endif
3886     }
3887     FOR_EACH_RESPONDER_SELECTOR(VALIDATE)
3888
3889     return YES;
3890 }
3891
3892 - (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item
3893 {
3894     BOOL result = [self validateUserInterfaceItemWithoutDelegate:item];
3895     return CallUIDelegateReturningBoolean(result, self, @selector(webView:validateUserInterfaceItem:defaultValidation:), item, result);
3896 }
3897
3898 @end
3899
3900 @implementation WebView (WebPendingPublic)
3901
3902 - (void)scheduleInRunLoop:(NSRunLoop *)runLoop forMode:(NSString *)mode
3903 {
3904     if (runLoop && mode)
3905         core(self)->addSchedulePair(SchedulePair::create(runLoop, (CFStringRef)mode));
3906 }
3907
3908 - (void)unscheduleFromRunLoop:(NSRunLoop *)runLoop forMode:(NSString *)mode
3909 {
3910     if (runLoop && mode)
3911         core(self)->removeSchedulePair(SchedulePair::create(runLoop, (CFStringRef)mode));
3912 }
3913
3914 - (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag startInSelection:(BOOL)startInSelection
3915 {
3916     if (_private->closed)
3917         return NO;
3918     
3919     // Get the frame holding the selection, or start with the main frame
3920     WebFrame *startFrame = [self _selectedOrMainFrame];
3921     
3922     // Search the first frame, then all the other frames, in order
3923     NSView <WebDocumentSearching> *startSearchView = nil;
3924     WebFrame *frame = startFrame;
3925     do {
3926         WebFrame *nextFrame = incrementFrame(frame, forward, wrapFlag);
3927         
3928         BOOL onlyOneFrame = (frame == nextFrame);
3929         ASSERT(!onlyOneFrame || frame == startFrame);
3930         
3931         id <WebDocumentView> view = [[frame frameView] documentView];
3932         if ([view conformsToProtocol:@protocol(WebDocumentSearching)]) {
3933             NSView <WebDocumentSearching> *searchView = (NSView <WebDocumentSearching> *)view;
3934             
3935             if (frame == startFrame)
3936                 startSearchView = searchView;
3937             
3938             BOOL foundString;
3939             // In some cases we have to search some content twice; see comment later in this method.
3940             // We can avoid ever doing this in the common one-frame case by passing YES for wrapFlag 
3941             // here, and then bailing out before we get to the code that would search again in the
3942             // same content.
3943             BOOL wrapOnThisPass = wrapFlag && onlyOneFrame;
3944             if ([searchView conformsToProtocol:@protocol(WebDocumentIncrementalSearching)])
3945                 foundString = [(NSView <WebDocumentIncrementalSearching> *)searchView searchFor:string direction:forward caseSensitive:caseFlag wrap:wrapOnThisPass startInSelection:startInSelection];
3946             else
3947                 foundString = [searchView searchFor:string direction:forward caseSensitive:caseFlag wrap:wrapOnThisPass];
3948             
3949             if (foundString) {
3950                 if (frame != startFrame)
3951                     [startFrame _clearSelection];
3952                 [[self window] makeFirstResponder:searchView];
3953                 return YES;
3954             }
3955             
3956             if (onlyOneFrame)
3957                 return NO;
3958         }
3959         frame = nextFrame;
3960     } while (frame && frame != startFrame);
3961     
3962     // If there are multiple frames and wrapFlag is true and we've visited each one without finding a result, we still need to search in the 
3963     // first-searched frame up to the selection. However, the API doesn't provide a way to search only up to a particular point. The only 
3964     // way to make sure the entire frame is searched is to pass YES for the wrapFlag. When there are no matches, this will search again
3965     // some content that we already searched on the first pass. In the worst case, we could search the entire contents of this frame twice.
3966     // To fix this, we'd need to add a mechanism to specify a range in which to search.
3967     if (wrapFlag && startSearchView) {
3968         BOOL foundString;
3969         if ([startSearchView conformsToProtocol:@protocol(WebDocumentIncrementalSearching)])
3970             foundString = [(NSView <WebDocumentIncrementalSearching> *)startSearchView searchFor:string direction:forward caseSensitive:caseFlag wrap:YES startInSelection:startInSelection];
3971         else
3972             foundString = [startSearchView searchFor:string direction:forward caseSensitive:caseFlag wrap:YES];
3973         if (foundString) {
3974             [[self window] makeFirstResponder:startSearchView];
3975             return YES;
3976         }
3977     }
3978     return NO;
3979 }
3980
3981 - (void)setHoverFeedbackSuspended:(BOOL)newValue
3982 {
3983     if (_private->hoverFeedbackSuspended == newValue)
3984         return;
3985     
3986     _private->hoverFeedbackSuspended = newValue;
3987
3988     if (_private->usesDocumentViews) {
3989         id <WebDocumentView> documentView = [[[self mainFrame] frameView] documentView];
3990         // FIXME: in a perfect world we'd do this in a general way that worked with any document view,
3991         // such as by calling a protocol method or using respondsToSelector or sending a notification.
3992         // But until there is any need for these more general solutions, we'll just hardwire it to work
3993         // with WebHTMLView.
3994         // Note that _hoverFeedbackSuspendedChanged needs to be called only on the main WebHTMLView, not
3995         // on each subframe separately.
3996         if ([documentView isKindOfClass:[WebHTMLView class]])
3997             [(WebHTMLView *)documentView _hoverFeedbackSuspendedChanged];
3998         return;
3999     }
4000
4001     [self _updateMouseoverWithFakeEvent];
4002 }
4003
4004 - (BOOL)isHoverFeedbackSuspended
4005 {
4006     return _private->hoverFeedbackSuspended;
4007 }
4008
4009 - (void)setMainFrameDocumentReady:(BOOL)mainFrameDocumentReady
4010 {
4011     // by setting this to NO, calls to mainFrameDocument are forced to return nil
4012     // setting this to YES lets it return the actual DOMDocument value
4013     // we use this to tell NSTreeController to reset its observers and clear its state
4014     if (_private->mainFrameDocumentReady == mainFrameDocumentReady)
4015         return;
4016     [self _willChangeValueForKey:_WebMainFrameDocumentKey];
4017     _private->mainFrameDocumentReady = mainFrameDocumentReady;
4018     [self _didChangeValueForKey:_WebMainFrameDocumentKey];
4019     // this will cause observers to call mainFrameDocument where this flag will be checked
4020 }
4021
4022 // This method name is used by Mail on Tiger (but not post-Tiger), so we shouldn't delete it 
4023 // until the day comes when we're no longer supporting Mail on Tiger.
4024 - (WebFrame *)_frameForCurrentSelection
4025 {
4026     return [self _selectedOrMainFrame];
4027 }
4028
4029 - (void)setTabKeyCyclesThroughElements:(BOOL)cyclesElements
4030 {
4031     _private->tabKeyCyclesThroughElementsChanged = YES;
4032     if (_private->page)
4033         _private->page->setTabKeyCyclesThroughElements(cyclesElements);
4034 }
4035
4036 - (BOOL)tabKeyCyclesThroughElements
4037 {
4038     return _private->page && _private->page->tabKeyCyclesThroughElements();
4039 }
4040
4041 - (void)setScriptDebugDelegate:(id)delegate
4042 {
4043     _private->scriptDebugDelegate = delegate;
4044     [self _cacheScriptDebugDelegateImplementations];
4045
4046     if (delegate)
4047         [self _attachScriptDebuggerToAllFrames];
4048     else
4049         [self _detachScriptDebuggerFromAllFrames];
4050 }
4051
4052 - (id)scriptDebugDelegate
4053 {
4054     return _private->scriptDebugDelegate;
4055 }
4056   
4057 - (void)setHistoryDelegate:(id)delegate
4058 {
4059     _private->historyDelegate = delegate;
4060     [self _cacheHistoryDelegateImplementations];
4061 }
4062
4063 - (id)historyDelegate
4064 {
4065     return _private->historyDelegate;
4066 }
4067
4068 - (BOOL)shouldClose
4069 {
4070     Frame* coreFrame = [self _mainCoreFrame];
4071     if (!coreFrame)
4072         return YES;
4073     return coreFrame->shouldClose();
4074 }
4075
4076 static NSAppleEventDescriptor* aeDescFromJSValue(ExecState* exec, JSValue jsValue)
4077 {
4078     NSAppleEventDescriptor* aeDesc = 0;
4079     if (jsValue.isBoolean())
4080         return [NSAppleEventDescriptor descriptorWithBoolean:jsValue.getBoolean()];
4081     if (jsValue.isString())
4082         return [NSAppleEventDescriptor descriptorWithString:String(jsValue.getString(exec))];
4083     if (jsValue.isNumber()) {
4084         double value = jsValue.uncheckedGetNumber();
4085         int intValue = value;
4086         if (value == intValue)
4087             return [NSAppleEventDescriptor descriptorWithDescriptorType:typeSInt32 bytes:&intValue length:sizeof(intValue)];
4088         return [NSAppleEventDescriptor descriptorWithDescriptorType:typeIEEE64BitFloatingPoint bytes:&value length:sizeof(value)];
4089     }
4090     if (jsValue.isObject()) {
4091         JSObject* object = jsValue.getObject();
4092         if (object->inherits(&DateInstance::info)) {
4093             DateInstance* date = static_cast<DateInstance*>(object);
4094             double ms = date->internalNumber();
4095             if (!isnan(ms)) {
4096                 CFAbsoluteTime utcSeconds = ms / 1000 - kCFAbsoluteTimeIntervalSince1970;
4097                 LongDateTime ldt;
4098                 if (noErr == UCConvertCFAbsoluteTimeToLongDateTime(utcSeconds, &ldt))
4099                     return [NSAppleEventDescriptor descriptorWithDescriptorType:typeLongDateTime bytes:&ldt length:sizeof(ldt)];
4100             }
4101         }
4102         else if (object->inherits(&JSArray::info)) {
4103             DEFINE_STATIC_LOCAL(HashSet<JSObject*>, visitedElems, ());
4104             if (!visitedElems.contains(object)) {
4105                 visitedElems.add(object);
4106                 
4107                 JSArray* array = static_cast<JSArray*>(object);
4108                 aeDesc = [NSAppleEventDescriptor listDescriptor];
4109                 unsigned numItems = array->length();
4110                 for (unsigned i = 0; i < numItems; ++i)
4111                     [aeDesc insertDescriptor:aeDescFromJSValue(exec, array->get(exec, i)) atIndex:0];
4112                 
4113                 visitedElems.remove(object);
4114                 return aeDesc;
4115             }
4116         }
4117         JSValue primitive = object->toPrimitive(exec);
4118         if (exec->hadException()) {
4119             exec->clearException();
4120             return [NSAppleEventDescriptor nullDescriptor];
4121         }
4122         return aeDescFromJSValue(exec, primitive);
4123     }
4124     if (jsValue.isUndefined())
4125         return [NSAppleEventDescriptor descriptorWithTypeCode:cMissingValue];
4126     ASSERT(jsValue.isNull());
4127     return [NSAppleEventDescriptor nullDescriptor];
4128 }
4129
4130 - (NSAppleEventDescriptor *)aeDescByEvaluatingJavaScriptFromString:(NSString *)script
4131 {
4132     Frame* coreFrame = [self _mainCoreFrame];
4133     if (!coreFrame)
4134         return nil;
4135     if (!coreFrame->document())
4136         return nil;
4137     JSValue result = coreFrame->script()->executeScript(script, true).jsValue();
4138     if (!result) // FIXME: pass errors
4139         return 0;
4140     JSLock lock(SilenceAssertionsOnly);
4141     return aeDescFromJSValue(coreFrame->script()->globalObject(mainThreadNormalWorld())->globalExec(), result);
4142 }
4143
4144 - (BOOL)canMarkAllTextMatches
4145 {
4146     WebFrame *frame = [self mainFrame];
4147     do {
4148         id <WebDocumentView> view = [[frame frameView] documentView];
4149         if (view && ![view conformsToProtocol:@protocol(WebMultipleTextMatches)])
4150             return NO;
4151         
4152         frame = incrementFrame(frame, YES, NO);
4153     } while (frame);
4154     
4155     return YES;
4156 }
4157
4158 - (NSUInteger)markAllMatchesForText:(NSString *)string caseSensitive:(BOOL)caseFlag highlight:(BOOL)highlight limit:(NSUInteger)limit
4159 {
4160     WebFrame *frame = [self mainFrame];
4161     unsigned matchCount = 0;
4162     do {
4163         id <WebDocumentView> view = [[frame frameView] documentView];
4164         if ([view conformsToProtocol:@protocol(WebMultipleTextMatches)]) {
4165             [(NSView <WebMultipleTextMatches>*)view  setMarkedTextMatchesAreHighlighted:highlight];
4166         
4167             ASSERT(limit == 0 || matchCount < limit);
4168             matchCount += [(NSView <WebMultipleTextMatches>*)view markAllMatchesForText:string caseSensitive:caseFlag limit:limit == 0 ? 0 : limit - matchCount];
4169
4170             // Stop looking if we've reached the limit. A limit of 0 means no limit.
4171             if (limit > 0 && matchCount >= limit)
4172                 break;
4173         }
4174         
4175         frame = incrementFrame(frame, YES, NO);
4176     } while (frame);
4177     
4178     return matchCount;
4179 }
4180
4181 - (void)unmarkAllTextMatches
4182 {
4183     WebFrame *frame = [self mainFrame];
4184     do {
4185         id <WebDocumentView> view = [[frame frameView] documentView];
4186         if ([view conformsToProtocol:@protocol(WebMultipleTextMatches)])
4187             [(NSView <WebMultipleTextMatches>*)view unmarkAllTextMatches];
4188         
4189         frame = incrementFrame(frame, YES, NO);
4190     } while (frame);
4191 }
4192
4193 - (NSArray *)rectsForTextMatches
4194 {
4195     NSMutableArray *result = [NSMutableArray array];
4196     WebFrame *frame = [self mainFrame];
4197     do {
4198         id <WebDocumentView> view = [[frame frameView] documentView];
4199         if ([view conformsToProtocol:@protocol(WebMultipleTextMatches)]) {
4200             NSView <WebMultipleTextMatches> *documentView = (NSView <WebMultipleTextMatches> *)view;
4201             NSRect documentViewVisibleRect = [documentView visibleRect];
4202             NSArray *originalRects = [documentView rectsForTextMatches];
4203             unsigned rectCount = [originalRects count];
4204             unsigned rectIndex;
4205             NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
4206             for (rectIndex = 0; rectIndex < rectCount; ++rectIndex) {
4207                 NSRect r = [[originalRects objectAtIndex:rectIndex] rectValue];
4208                 // Clip rect to document view's visible rect so rect is confined to subframe
4209                 r = NSIntersectionRect(r, documentViewVisibleRect);
4210                 if (NSIsEmptyRect(r))
4211                     continue;
4212                 
4213                 // Convert rect to our coordinate system
4214                 r = [documentView convertRect:r toView:self];
4215                 [result addObject:[NSValue valueWithRect:r]];
4216                 if (rectIndex % 10 == 0) {
4217                     [pool drain];
4218                     pool = [[NSAutoreleasePool alloc] init];
4219                 }
4220             }
4221             [pool drain];
4222         }
4223         
4224         frame = incrementFrame(frame, YES, NO);
4225     } while (frame);
4226     
4227     return result;
4228 }
4229
4230 - (void)scrollDOMRangeToVisible:(DOMRange *)range
4231 {
4232     [[[[range startContainer] ownerDocument] webFrame] _scrollDOMRangeToVisible:range];
4233 }
4234
4235 - (BOOL)allowsUndo
4236 {
4237     return _private->allowsUndo;
4238 }
4239
4240 - (void)setAllowsUndo:(BOOL)flag
4241 {
4242     _private->allowsUndo = flag;
4243 }
4244
4245 - (void)setPageSizeMultiplier:(float)m
4246 {
4247     [self _setZoomMultiplier:m isTextOnly:NO];
4248 }
4249
4250 - (float)pageSizeMultiplier
4251 {
4252     return ![self _realZoomMultiplierIsTextOnly] ? _private->zoomMultiplier : 1.0f;
4253 }
4254
4255 - (BOOL)canZoomPageIn
4256 {
4257     return [self _canZoomIn:NO];
4258 }
4259
4260 - (IBAction)zoomPageIn:(id)sender
4261 {
4262     return [self _zoomIn:sender isTextOnly:NO];
4263 }
4264
4265 - (BOOL)canZoomPageOut
4266 {
4267     return [self _canZoomOut:NO];
4268 }
4269
4270 - (IBAction)zoomPageOut:(id)sender
4271 {
4272     return [self _zoomOut:sender isTextOnly:NO];
4273 }
4274
4275 - (BOOL)canResetPageZoom
4276 {
4277     return [self _canResetZoom:NO];
4278 }
4279
4280 - (IBAction)resetPageZoom:(id)sender
4281 {
4282     return [self _resetZoom:sender isTextOnly:NO];
4283 }
4284
4285 - (void)setMediaVolume:(float)volume
4286 {
4287     if (_private->page)
4288         _private->page->setMediaVolume(volume);
4289 }
4290
4291 - (float)mediaVolume
4292 {
4293     if (!_private->page)
4294         return 0;
4295
4296     return _private->page->mediaVolume();
4297 }
4298
4299 - (void)addVisitedLinks:(NSArray *)visitedLinks
4300 {
4301     PageGroup& group = core(self)->group();
4302     
4303     NSEnumerator *enumerator = [visitedLinks objectEnumerator];
4304     while (NSString *url = [enumerator nextObject]) {
4305         size_t length = [url length];
4306         const UChar* characters = CFStringGetCharactersPtr(reinterpret_cast<CFStringRef>(url));
4307         if (characters)
4308             group.addVisitedLink(characters, length);
4309         else {
4310             Vector<UChar, 512> buffer(length);
4311             [url getCharacters:buffer.data()];
4312             group.addVisitedLink(buffer.data(), length);
4313         }
4314     }
4315 }
4316
4317 @end
4318
4319 @implementation WebView (WebViewPrintingPrivate)
4320
4321 - (float)_headerHeight
4322 {
4323     return CallUIDelegateReturningFloat(self, @selector(webViewHeaderHeight:));
4324 }
4325
4326 - (float)_footerHeight
4327 {
4328     return CallUIDelegateReturningFloat(self, @selector(webViewFooterHeight:));
4329 }
4330
4331 - (void)_drawHeaderInRect:(NSRect)rect
4332 {
4333 #ifdef DEBUG_HEADER_AND_FOOTER
4334     NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
4335     [currentContext saveGraphicsState];
4336     [[NSColor yellowColor] set];
4337     NSRectFill(rect);
4338     [currentContext restoreGraphicsState];
4339 #endif
4340
4341     SEL selector = @selector(webView:drawHeaderInRect:);
4342     if (![_private->UIDelegate respondsToSelector:selector])
4343         return;
4344
4345     NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
4346     [currentContext saveGraphicsState];
4347
4348     NSRectClip(rect);
4349     CallUIDelegate(self, selector, rect);
4350
4351     [currentContext restoreGraphicsState];
4352 }
4353
4354 - (void)_drawFooterInRect:(NSRect)rect
4355 {
4356 #ifdef DEBUG_HEADER_AND_FOOTER
4357     NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
4358     [currentContext saveGraphicsState];
4359     [[NSColor cyanColor] set];
4360     NSRectFill(rect);
4361     [currentContext restoreGraphicsState];
4362 #endif
4363     
4364     SEL selector = @selector(webView:drawFooterInRect:);
4365     if (![_private->UIDelegate respondsToSelector:selector])
4366         return;
4367
4368     NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
4369     [currentContext saveGraphicsState];
4370
4371     NSRectClip(rect);
4372     CallUIDelegate(self, selector, rect);
4373
4374     [currentContext restoreGraphicsState];
4375 }
4376
4377 - (void)_adjustPrintingMarginsForHeaderAndFooter
4378 {
4379     NSPrintOperation *op = [NSPrintOperation currentOperation];
4380     NSPrintInfo *info = [op printInfo];
4381     NSMutableDictionary *infoDictionary = [info dictionary];
4382     
4383     // We need to modify the top and bottom margins in the NSPrintInfo to account for the space needed by the
4384     // header and footer. Because this method can be called more than once on the same NSPrintInfo (see 5038087),
4385     // we stash away the unmodified top and bottom margins the first time this method is called, and we read from
4386     // those stashed-away values on subsequent calls.
4387     float originalTopMargin;
4388     float originalBottomMargin;
4389     NSNumber *originalTopMarginNumber = [infoDictionary objectForKey:WebKitOriginalTopPrintingMarginKey];
4390     if (!originalTopMarginNumber) {
4391         ASSERT(![infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey]);
4392         originalTopMargin = [info topMargin];
4393         originalBottomMargin = [info bottomMargin];
4394         [infoDictionary setObject:[NSNumber numberWithFloat:originalTopMargin] forKey:WebKitOriginalTopPrintingMarginKey];
4395         [infoDictionary setObject:[NSNumber numberWithFloat:originalBottomMargin] forKey:WebKitOriginalBottomPrintingMarginKey];
4396     } else {
4397         ASSERT([originalTopMarginNumber isKindOfClass:[NSNumber class]]);
4398         ASSERT([[infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey] isKindOfClass:[NSNumber class]]);
4399         originalTopMargin = [originalTopMarginNumber floatValue];
4400         originalBottomMargin = [[infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey] floatValue];
4401     }
4402     
4403     float scale = [op _web_pageSetupScaleFactor];
4404     [info setTopMargin:originalTopMargin + [self _headerHeight] * scale];
4405     [info setBottomMargin:originalBottomMargin + [self _footerHeight] * scale];
4406 }
4407
4408 - (void)_drawHeaderAndFooter
4409 {
4410     // The header and footer rect height scales with the page, but the width is always
4411     // all the way across the printed page (inset by printing margins).
4412     NSPrintOperation *op = [NSPrintOperation currentOperation];
4413     float scale = [op _web_pageSetupScaleFactor];
4414     NSPrintInfo *printInfo = [op printInfo];
4415     NSSize paperSize = [printInfo paperSize];
4416     float headerFooterLeft = [printInfo leftMargin]/scale;
4417     float headerFooterWidth = (paperSize.width - ([printInfo leftMargin] + [printInfo rightMargin]))/scale;
4418     NSRect footerRect = NSMakeRect(headerFooterLeft, [printInfo bottomMargin]/scale - [self _footerHeight] , 
4419                                    headerFooterWidth, [self _footerHeight]);
4420     NSRect headerRect = NSMakeRect(headerFooterLeft, (paperSize.height - [printInfo topMargin])/scale, 
4421                                    headerFooterWidth, [self _headerHeight]);
4422     
4423     [self _drawHeaderInRect:headerRect];
4424     [self _drawFooterInRect:footerRect];
4425 }
4426 @end
4427
4428 @implementation WebView (WebDebugBinding)
4429
4430 - (void)addObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context
4431 {
4432     LOG (Bindings, "addObserver:%p forKeyPath:%@ options:%x context:%p", anObserver, keyPath, options, context);
4433     [super addObserver:anObserver forKeyPath:keyPath options:options context:context];
4434 }
4435
4436 - (void)removeObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath
4437 {
4438     LOG (Bindings, "removeObserver:%p forKeyPath:%@", anObserver, keyPath);
4439     [super removeObserver:anObserver forKeyPath:keyPath];
4440 }
4441
4442 @end
4443
4444 //==========================================================================================
4445 // Editing
4446
4447 @implementation WebView (WebViewCSS)
4448
4449 - (DOMCSSStyleDeclaration *)computedStyleForElement:(DOMElement *)element pseudoElement:(NSString *)pseudoElement
4450 {
4451     // FIXME: is this the best level for this conversion?
4452     if (pseudoElement == nil)
4453         pseudoElement = @"";
4454
4455     return [[element ownerDocument] getComputedStyle:element pseudoElement:pseudoElement];
4456 }
4457
4458 @end
4459
4460 @implementation WebView (WebViewEditing)
4461
4462 - (DOMRange *)editableDOMRangeForPoint:(NSPoint)point
4463<