d5e6cc61ea3e2421b90a7f5e605ca81afa0c4dd8
[WebKit-https.git] / WebKit / WebView / WebView.m
1 /*
2  * Copyright (C) 2005, 2006 Apple Computer, Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer. 
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution. 
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission. 
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #import "WebViewInternal.h"
30
31 #import <JavaScriptCore/Assertions.h>
32 #import "WebBackForwardList.h"
33 #import "WebBaseNetscapePluginView.h"
34 #import "WebDOMOperationsPrivate.h"
35 #import "WebDashboardRegion.h"
36 #import "WebDataProtocol.h"
37 #import "WebDataSourceInternal.h"
38 #import "WebDefaultEditingDelegate.h"
39 #import "WebDefaultFrameLoadDelegate.h"
40 #import "WebDefaultPolicyDelegate.h"
41 #import "WebDefaultResourceLoadDelegate.h"
42 #import "WebDefaultScriptDebugDelegate.h"
43 #import "WebDefaultUIDelegate.h"
44 #import "WebDocument.h"
45 #import "WebDocumentInternal.h"
46 #import "WebDownload.h"
47 #import "WebDownloadInternal.h"
48 #import "WebDynamicScrollBarsView.h"
49 #import "WebEditingDelegate.h"
50 #import "WebFormDelegatePrivate.h"
51 #import "WebFrameBridge.h"
52 #import "WebFrameInternal.h"
53 #import "WebFrameLoader.h"
54 #import "WebFrameViewInternal.h"
55 #import "WebHTMLRepresentation.h"
56 #import "WebHTMLViewInternal.h"
57 #import "WebHistoryItemPrivate.h"
58 #import "WebIconDatabase.h"
59 #import "WebInspector.h"
60 #import "WebKitErrors.h"
61 #import "WebKitLogging.h"
62 #import "WebKitNSStringExtras.h"
63 #import "WebKitStatisticsPrivate.h"
64 #import "WebLocalizableStrings.h"
65 #import "WebNSDataExtras.h"
66 #import "WebNSDataExtrasPrivate.h"
67 #import "WebNSDictionaryExtras.h"
68 #import "WebNSEventExtras.h"
69 #import "WebNSObjectExtras.h"
70 #import "WebNSPasteboardExtras.h"
71 #import "WebNSPrintOperationExtras.h"
72 #import "WebNSURLExtras.h"
73 #import "WebNSURLRequestExtras.h"
74 #import "WebNSUserDefaultsExtras.h"
75 #import "WebNSViewExtras.h"
76 #import "WebPageBridge.h"
77 #import "WebPDFView.h"
78 #import "WebPluginDatabase.h"
79 #import "WebPolicyDelegate.h"
80 #import "WebPreferencesPrivate.h"
81 #import "WebResourceLoadDelegate.h"
82 #import "WebScriptDebugDelegatePrivate.h"
83 #import "WebScriptDebugServerPrivate.h"
84 #import "WebUIDelegate.h"
85 #import "WebUIDelegatePrivate.h"
86 #import <CoreFoundation/CFSet.h>
87 #import <Foundation/NSURLConnection.h>
88 #import <WebCore/WebCoreEncodings.h>
89 #import <WebCore/WebCoreFrameBridge.h>
90 #import <WebCore/WebCoreSettings.h>
91 #import <WebCore/WebCoreView.h>
92 #import <WebKit/DOM.h>
93 #import <WebKit/DOMPrivate.h>
94 #import <WebKit/DOMExtensions.h>
95 #import <WebKitSystemInterface.h>
96 #import <objc/objc-runtime.h>
97
98 #import <WebCore/WebCoreTextRenderer.h>
99
100 #if defined(__ppc__) || defined(__ppc64__)
101 #define PROCESSOR "PPC"
102 #elif defined(__i386__) || defined(__x86_64__)
103 #define PROCESSOR "Intel"
104 #else
105 #error Unknown architecture
106 #endif
107
108 #define FOR_EACH_RESPONDER_SELECTOR(macro) \
109 macro(alignCenter) \
110 macro(alignJustified) \
111 macro(alignLeft) \
112 macro(alignRight) \
113 macro(capitalizeWord) \
114 macro(centerSelectionInVisibleArea) \
115 macro(changeAttributes) \
116 macro(changeColor) \
117 macro(changeDocumentBackgroundColor) \
118 macro(changeFont) \
119 macro(checkSpelling) \
120 macro(complete) \
121 macro(copy) \
122 macro(copyFont) \
123 macro(cut) \
124 macro(delete) \
125 macro(deleteBackward) \
126 macro(deleteBackwardByDecomposingPreviousCharacter) \
127 macro(deleteForward) \
128 macro(deleteToBeginningOfLine) \
129 macro(deleteToBeginningOfParagraph) \
130 macro(deleteToEndOfLine) \
131 macro(deleteToEndOfParagraph) \
132 macro(deleteWordBackward) \
133 macro(deleteWordForward) \
134 macro(ignoreSpelling) \
135 macro(indent) \
136 macro(insertBacktab) \
137 macro(insertNewline) \
138 macro(insertNewlineIgnoringFieldEditor) \
139 macro(insertParagraphSeparator) \
140 macro(insertTab) \
141 macro(insertTabIgnoringFieldEditor) \
142 macro(lowercaseWord) \
143 macro(moveBackward) \
144 macro(moveBackwardAndModifySelection) \
145 macro(moveDown) \
146 macro(moveDownAndModifySelection) \
147 macro(moveForward) \
148 macro(moveForwardAndModifySelection) \
149 macro(moveLeft) \
150 macro(moveLeftAndModifySelection) \
151 macro(moveRight) \
152 macro(moveRightAndModifySelection) \
153 macro(moveToBeginningOfDocument) \
154 macro(moveToBeginningOfDocumentAndModifySelection) \
155 macro(moveToBeginningOfSentence) \
156 macro(moveToBeginningOfSentenceAndModifySelection) \
157 macro(moveToBeginningOfLine) \
158 macro(moveToBeginningOfLineAndModifySelection) \
159 macro(moveToBeginningOfParagraph) \
160 macro(moveToBeginningOfParagraphAndModifySelection) \
161 macro(moveToEndOfDocument) \
162 macro(moveToEndOfDocumentAndModifySelection) \
163 macro(moveToEndOfLine) \
164 macro(moveToEndOfLineAndModifySelection) \
165 macro(moveToEndOfParagraph) \
166 macro(moveToEndOfParagraphAndModifySelection) \
167 macro(moveToEndOfSentence) \
168 macro(moveToEndOfSentenceAndModifySelection) \
169 macro(moveUp) \
170 macro(moveUpAndModifySelection) \
171 macro(moveWordBackward) \
172 macro(moveWordBackwardAndModifySelection) \
173 macro(moveWordForward) \
174 macro(moveWordForwardAndModifySelection) \
175 macro(moveWordLeft) \
176 macro(moveWordLeftAndModifySelection) \
177 macro(moveWordRight) \
178 macro(moveWordRightAndModifySelection) \
179 macro(pageDown) \
180 macro(pageUp) \
181 macro(paste) \
182 macro(pasteAsPlainText) \
183 macro(pasteAsRichText) \
184 macro(pasteFont) \
185 macro(performFindPanelAction) \
186 macro(scrollLineDown) \
187 macro(scrollLineUp) \
188 macro(scrollPageDown) \
189 macro(scrollPageUp) \
190 macro(scrollToBeginningOfDocument) \
191 macro(scrollToEndOfDocument) \
192 macro(selectAll) \
193 macro(selectWord) \
194 macro(selectSentence) \
195 macro(selectLine) \
196 macro(selectParagraph) \
197 macro(showGuessPanel) \
198 macro(startSpeaking) \
199 macro(stopSpeaking) \
200 macro(subscript) \
201 macro(superscript) \
202 macro(underline) \
203 macro(unscript) \
204 macro(uppercaseWord) \
205 macro(yank) \
206 macro(yankAndSelect) \
207
208 @interface NSSpellChecker (AppKitSecretsIKnow)
209 - (void)_preflightChosenSpellServer;
210 @end
211
212 @interface NSView (AppKitSecretsIKnow)
213 - (NSView *)_hitTest:(NSPoint *)aPoint dragTypes:(NSSet *)types;
214 - (void)_autoscrollForDraggingInfo:(id)dragInfo timeDelta:(NSTimeInterval)repeatDelta;
215 - (BOOL)_shouldAutoscrollForDraggingInfo:(id)dragInfo;
216 @end
217
218 @interface WebViewPrivate : NSObject
219 {
220 @public
221     WebPageBridge *_pageBridge;
222     
223     id UIDelegate;
224     id UIDelegateForwarder;
225     id resourceProgressDelegate;
226     id resourceProgressDelegateForwarder;
227     id downloadDelegate;
228     id policyDelegate;
229     id policyDelegateForwarder;
230     id frameLoadDelegate;
231     id frameLoadDelegateForwarder;
232     id <WebFormDelegate> formDelegate;
233     id editingDelegate;
234     id editingDelegateForwarder;
235     id scriptDebugDelegate;
236     id scriptDebugDelegateForwarder;
237     
238     WebBackForwardList *backForwardList;
239     BOOL useBackForwardList;
240     
241     float textSizeMultiplier;
242
243     NSString *applicationNameForUserAgent;
244     NSString *userAgent;
245     BOOL userAgentOverridden;
246     
247     BOOL defersCallbacks;
248
249     WebPreferences *preferences;
250     WebCoreSettings *settings;
251         
252     BOOL lastElementWasNonNil;
253
254     NSWindow *hostWindow;
255
256     int programmaticFocusCount;
257     
258     WebResourceDelegateImplementationCache resourceLoadDelegateImplementations;
259
260     long long totalPageAndResourceBytesToLoad;
261     long long totalBytesReceived;
262     double progressValue;
263     double lastNotifiedProgressValue;
264     double lastNotifiedProgressTime;
265     double progressNotificationInterval;
266     double progressNotificationTimeInterval;
267     BOOL finalProgressChangedSent;
268     WebFrame *originatingProgressFrame;
269     
270     int numProgressTrackedFrames;
271     NSMutableDictionary *progressItems;
272     
273     void *observationInfo;
274     
275     BOOL closed;
276     BOOL shouldCloseWithWindow;
277     BOOL mainFrameDocumentReady;
278     BOOL drawsBackground;
279     BOOL editable;
280     BOOL initiatedDrag;
281     BOOL tabKeyCyclesThroughElements;
282     BOOL tabKeyCyclesThroughElementsChanged;
283
284     NSString *mediaStyle;
285     
286     NSView <WebDocumentDragging> *draggingDocumentView;
287     unsigned int dragDestinationActionMask;
288     
289     BOOL hasSpellCheckerDocumentTag;
290     WebNSInteger spellCheckerDocumentTag;
291
292     BOOL continuousSpellCheckingEnabled;
293     BOOL smartInsertDeleteEnabled;
294     
295     BOOL dashboardBehaviorAlwaysSendMouseEventsToAllWindows;
296     BOOL dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns;
297     BOOL dashboardBehaviorAlwaysAcceptsFirstMouse;
298     BOOL dashboardBehaviorAllowWheelScrolling;
299     
300     BOOL selectWordBeforeMenuEvent;
301     
302     WebPluginDatabase *pluginDatabase;
303 }
304 @end
305
306 @interface WebView (WebFileInternal)
307 - (WebFrame *)_selectedOrMainFrame;
308 - (WebFrameBridge *)_bridgeForSelectedOrMainFrame;
309 - (BOOL)_isLoading;
310 - (WebFrameView *)_frameViewAtWindowPoint:(NSPoint)point;
311 - (WebFrameBridge *)_bridgeAtPoint:(NSPoint)point;
312 - (WebFrame *)_focusedFrame;
313 + (void)_preflightSpellChecker;
314 - (BOOL)_continuousCheckingAllowed;
315 - (NSResponder *)_responderForResponderOperations;
316 - (BOOL)_performTextSizingSelector:(SEL)sel withObject:(id)arg onTrackingDocs:(BOOL)doTrackingViews selForNonTrackingDocs:(SEL)testSel newScaleFactor:(float)newScaleFactor;
317 @end
318
319 NSString *WebElementDOMNodeKey =            @"WebElementDOMNode";
320 NSString *WebElementFrameKey =              @"WebElementFrame";
321 NSString *WebElementImageKey =              @"WebElementImage";
322 NSString *WebElementImageAltStringKey =     @"WebElementImageAltString";
323 NSString *WebElementImageRectKey =          @"WebElementImageRect";
324 NSString *WebElementImageURLKey =           @"WebElementImageURL";
325 NSString *WebElementIsSelectedKey =         @"WebElementIsSelected";
326 NSString *WebElementTitleKey =              @"WebElementTitle";
327 NSString *WebElementLinkURLKey =            @"WebElementLinkURL";
328 NSString *WebElementLinkTargetFrameKey =    @"WebElementTargetFrame";
329 NSString *WebElementLinkLabelKey =          @"WebElementLinkLabel";
330 NSString *WebElementLinkTitleKey =          @"WebElementLinkTitle";
331
332 NSString *WebViewProgressStartedNotification =          @"WebProgressStartedNotification";
333 NSString *WebViewProgressEstimateChangedNotification =  @"WebProgressEstimateChangedNotification";
334 NSString *WebViewProgressFinishedNotification =         @"WebProgressFinishedNotification";
335
336 NSString * const WebViewDidBeginEditingNotification =         @"WebViewDidBeginEditingNotification";
337 NSString * const WebViewDidChangeNotification =               @"WebViewDidChangeNotification";
338 NSString * const WebViewDidEndEditingNotification =           @"WebViewDidEndEditingNotification";
339 NSString * const WebViewDidChangeTypingStyleNotification =    @"WebViewDidChangeTypingStyleNotification";
340 NSString * const WebViewDidChangeSelectionNotification =      @"WebViewDidChangeSelectionNotification";
341
342 enum { WebViewVersion = 2 };
343
344 #define timedLayoutSize 4096
345
346 static NSMutableSet *schemesWithRepresentationsSet;
347
348 NSString *_WebCanGoBackKey =            @"canGoBack";
349 NSString *_WebCanGoForwardKey =         @"canGoForward";
350 NSString *_WebEstimatedProgressKey =    @"estimatedProgress";
351 NSString *_WebIsLoadingKey =            @"isLoading";
352 NSString *_WebMainFrameIconKey =        @"mainFrameIcon";
353 NSString *_WebMainFrameTitleKey =       @"mainFrameTitle";
354 NSString *_WebMainFrameURLKey =         @"mainFrameURL";
355 NSString *_WebMainFrameDocumentKey =    @"mainFrameDocument";
356
357 @interface WebProgressItem : NSObject
358 {
359 @public
360     long long bytesReceived;
361     long long estimatedLength;
362 }
363 @end
364
365 @implementation WebProgressItem
366 @end
367
368 @implementation WebViewPrivate
369
370 - init 
371 {
372     self = [super init];
373     if (!self)
374         return nil;
375     
376     backForwardList = [[WebBackForwardList alloc] init];
377     textSizeMultiplier = 1;
378     progressNotificationInterval = 0.02;
379     progressNotificationTimeInterval = 0.1;
380     settings = [[WebCoreSettings alloc] init];
381     dashboardBehaviorAllowWheelScrolling = YES;
382     tabKeyCyclesThroughElements = YES;
383     shouldCloseWithWindow = objc_collecting_enabled();
384
385     return self;
386 }
387
388 - (void)dealloc
389 {
390     ASSERT(!_pageBridge);
391     ASSERT(draggingDocumentView == nil);
392     
393     [backForwardList release];
394     [applicationNameForUserAgent release];
395     [userAgent release];
396     
397     [preferences release];
398     [settings release];
399     [hostWindow release];
400     
401     [policyDelegateForwarder release];
402     [resourceProgressDelegateForwarder release];
403     [UIDelegateForwarder release];
404     [frameLoadDelegateForwarder release];
405     [editingDelegateForwarder release];
406     [scriptDebugDelegateForwarder release];
407     
408     [progressItems release];
409         
410     [mediaStyle release];
411     
412     [super dealloc];
413 }
414
415 @end
416
417 @implementation WebView (AllWebViews)
418
419 static CFSetCallBacks NonRetainingSetCallbacks = {
420     0,
421     NULL,
422     NULL,
423     CFCopyDescription,
424     CFEqual,
425     CFHash
426 };
427
428 static CFMutableSetRef allWebViewsSet;
429
430 + (void)_makeAllWebViewsPerformSelector:(SEL)selector
431 {
432     if (!allWebViewsSet)
433         return;
434
435     [(NSMutableSet *)allWebViewsSet makeObjectsPerformSelector:selector];
436 }
437
438 - (void)_removeFromAllWebViewsSet
439 {
440     if (allWebViewsSet)
441         CFSetRemoveValue(allWebViewsSet, self);
442 }
443
444 - (void)_addToAllWebViewsSet
445 {
446     if (!allWebViewsSet)
447         allWebViewsSet = CFSetCreateMutable(NULL, 0, &NonRetainingSetCallbacks);
448
449     CFSetSetValue(allWebViewsSet, self);
450 }
451
452 @end
453
454 @implementation WebView (WebPrivate)
455
456 #ifdef DEBUG_WIDGET_DRAWING
457 static bool debugWidget = true;
458 - (void)drawRect:(NSRect)rect
459 {
460     [[NSColor blueColor] set];
461     NSRectFill (rect);
462     
463     NSRect htmlViewRect = [[[[self mainFrame] frameView] documentView] frame];
464
465     if (debugWidget) {
466         while (debugWidget) {
467             sleep (1);
468         }
469     }
470
471     NSLog (@"%s:   rect:  (%0.f,%0.f) %0.f %0.f, htmlViewRect:  (%0.f,%0.f) %0.f %0.f\n", 
472         __PRETTY_FUNCTION__, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height,
473         htmlViewRect.origin.x, htmlViewRect.origin.y, htmlViewRect.size.width, htmlViewRect.size.height
474     );
475
476     [super drawRect:rect];
477 }
478 #endif
479
480 + (BOOL)_developerExtrasEnabled
481 {
482 #ifdef NDEBUG
483     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
484     BOOL enableDebugger = [defaults boolForKey:@"WebKitDeveloperExtras"];
485     if (!enableDebugger)
486         enableDebugger = [defaults boolForKey:@"IncludeDebugMenu"];
487     return enableDebugger;
488 #else
489     return YES; // always enable in debug builds
490 #endif
491 }
492
493 + (BOOL)_scriptDebuggerEnabled
494 {
495 #ifdef NDEBUG
496     return [[NSUserDefaults standardUserDefaults] boolForKey:@"WebKitScriptDebuggerEnabled"];
497 #else
498     return YES; // always enable in debug builds
499 #endif
500 }
501
502 + (NSArray *)_supportedMIMETypes
503 {
504     // Load the plug-in DB allowing plug-ins to install types.
505     [WebPluginDatabase installedPlugins];
506     return [[WebFrameView _viewTypesAllowImageTypeOmission:NO] allKeys];
507 }
508
509 + (NSArray *)_supportedFileExtensions
510 {
511     NSMutableSet *extensions = [[NSMutableSet alloc] init];
512     NSArray *MIMETypes = [self _supportedMIMETypes];
513     NSEnumerator *enumerator = [MIMETypes objectEnumerator];
514     NSString *MIMEType;
515     while ((MIMEType = [enumerator nextObject]) != nil) {
516         NSArray *extensionsForType = WKGetExtensionsForMIMEType(MIMEType);
517         if (extensionsForType) {
518             [extensions addObjectsFromArray:extensionsForType];
519         }
520     }
521     NSArray *uniqueExtensions = [extensions allObjects];
522     [extensions release];
523     return uniqueExtensions;
524 }
525
526 + (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType;
527 {
528     MIMEType = [MIMEType lowercaseString];
529     Class viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:YES] _webkit_objectForMIMEType:MIMEType];
530     Class repClass = [[WebDataSource _repTypesAllowImageTypeOmission:YES] _webkit_objectForMIMEType:MIMEType];
531     
532     if (!viewClass || !repClass || [[WebPDFView supportedMIMETypes] containsObject:MIMEType]) {
533         // Our optimization to avoid loading the plug-in DB and image types for the HTML case failed.
534         // Load the plug-in DB allowing plug-ins to install types.
535         [WebPluginDatabase installedPlugins];
536             
537         // Load the image types and get the view class and rep class. This should be the fullest picture of all handled types.
538         viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:NO] _webkit_objectForMIMEType:MIMEType];
539         repClass = [[WebDataSource _repTypesAllowImageTypeOmission:NO] _webkit_objectForMIMEType:MIMEType];
540     }
541     
542     if (viewClass && repClass) {
543         // Special-case WebHTMLView for text types that shouldn't be shown.
544         if (viewClass == [WebHTMLView class] &&
545             repClass == [WebHTMLRepresentation class] &&
546             [[WebHTMLView unsupportedTextMIMETypes] containsObject:MIMEType]) {
547             return NO;
548         }
549         if (vClass)
550             *vClass = viewClass;
551         if (rClass)
552             *rClass = repClass;
553         return YES;
554     }
555     
556     return NO;
557 }
558
559 - (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType;
560 {
561     if ([[self class] _viewClass:vClass andRepresentationClass:rClass forMIMEType:MIMEType])
562         return YES;
563
564     if (_private->pluginDatabase) {
565         WebBasePluginPackage *pluginPackage = [_private->pluginDatabase pluginForMIMEType:MIMEType];
566         if (pluginPackage) {
567             if (vClass)
568                 *vClass = [WebHTMLView class];
569             if (rClass)
570                 *rClass = [WebHTMLRepresentation class];
571             return YES;
572         }
573     }
574     
575     return NO;
576 }
577
578 + (void)_setAlwaysUseATSU:(BOOL)f
579 {
580     WebCoreSetAlwaysUseATSU(f);
581 }
582
583 + (BOOL)canShowFile:(NSString *)path
584 {
585     return [[self class] canShowMIMEType:[WebView _MIMETypeForFile:path]];
586 }
587
588 + (NSString *)suggestedFileExtensionForMIMEType:(NSString *)type
589 {
590     return WKGetPreferredExtensionForMIMEType(type);
591 }
592
593 - (void)_close
594 {
595     if (!_private || _private->closed)
596         return;
597     _private->closed = YES;
598
599     [self _removeFromAllWebViewsSet];
600
601     [self setGroupName:nil];
602     [self setHostWindow:nil];
603     [self setDownloadDelegate:nil];
604     [self setEditingDelegate:nil];
605     [self setFrameLoadDelegate:nil];
606     [self setPolicyDelegate:nil];
607     [self setResourceLoadDelegate:nil];
608     [self setScriptDebugDelegate:nil];
609     [self setUIDelegate:nil];
610
611     // To avoid leaks, call removeDragCaret in case it wasn't called after moveDragCaretToPoint.
612     [self removeDragCaret];
613
614     [[self mainFrame] _detachFromParent];
615     [_private->_pageBridge close];
616     [_private->_pageBridge release];
617     _private->_pageBridge = nil;
618
619     // Clear the page cache so we call destroy on all the plug-ins in the page cache to break any retain cycles.
620     // See comment in [WebHistoryItem _releaseAllPendingPageCaches] for more information.
621     if (_private->backForwardList) {
622         [_private->backForwardList _close];
623         [_private->backForwardList release];
624         _private->backForwardList = nil;
625     }
626
627     if (_private->hasSpellCheckerDocumentTag) {
628         [[NSSpellChecker sharedSpellChecker] closeSpellDocumentWithTag:_private->spellCheckerDocumentTag];
629         _private->hasSpellCheckerDocumentTag = NO;
630     }
631
632     if (_private->pluginDatabase) {
633         [_private->pluginDatabase close];
634         [_private->pluginDatabase release];
635         _private->pluginDatabase = nil;
636     }
637
638     [[NSNotificationCenter defaultCenter] removeObserver:self];
639
640     [WebPreferences _removeReferenceForIdentifier: [self preferencesIdentifier]];
641 }
642
643 + (NSString *)_MIMETypeForFile:(NSString *)path
644 {
645     NSString *extension = [path pathExtension];
646     NSString *MIMEType = nil;
647
648     // Get the MIME type from the extension.
649     if ([extension length] != 0) {
650         MIMEType = WKGetMIMETypeForExtension(extension);
651     }
652
653     // If we can't get a known MIME type from the extension, sniff.
654     if ([MIMEType length] == 0 || [MIMEType isEqualToString:@"application/octet-stream"]) {
655         NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:path];
656         NSData *data = [handle readDataOfLength:WEB_GUESS_MIME_TYPE_PEEK_LENGTH];
657         [handle closeFile];
658         if ([data length] != 0) {
659             MIMEType = [data _webkit_guessedMIMEType];
660         }
661         if ([MIMEType length] == 0) {
662             MIMEType = @"application/octet-stream";
663         }
664     }
665
666     return MIMEType;
667 }
668
669 - (void)_downloadURL:(NSURL *)URL
670 {
671     ASSERT(URL);
672     
673     NSURLRequest *request = [[NSURLRequest alloc] initWithURL:URL];
674     [WebDownload _downloadWithRequest:request
675                              delegate:_private->downloadDelegate
676                             directory:nil];
677     [request release];
678 }
679
680 - (BOOL)defersCallbacks
681 {
682     return _private->defersCallbacks;
683 }
684
685 - (void)setDefersCallbacks:(BOOL)defers
686 {
687     if (defers == _private->defersCallbacks) {
688         return;
689     }
690
691     _private->defersCallbacks = defers;
692     [[self mainFrame] _defersCallbacksChanged];
693 }
694
695 - (WebView *)_openNewWindowWithRequest:(NSURLRequest *)request
696 {
697     id wd = [self UIDelegate];
698     WebView *newWindowWebView = nil;
699     if ([wd respondsToSelector:@selector(webView:createWebViewWithRequest:)])
700         newWindowWebView = [wd webView:self createWebViewWithRequest:request];
701     else {
702         newWindowWebView = [[WebDefaultUIDelegate sharedUIDelegate] webView:self createWebViewWithRequest: request];
703     }
704
705     [[newWindowWebView _UIDelegateForwarder] webViewShow: newWindowWebView];
706
707     return newWindowWebView;
708 }
709
710 - (NSMenu *)_menuForElement:(NSDictionary *)element defaultItems:(NSArray *)items
711 {
712     NSArray *defaultMenuItems = [[WebDefaultUIDelegate sharedUIDelegate]
713           webView:self contextMenuItemsForElement:element defaultMenuItems:items];
714     NSArray *menuItems = defaultMenuItems;
715     NSMenu *menu = nil;
716     unsigned i;
717
718     DOMNode* node = [element objectForKey:WebElementDOMNodeKey];
719     BOOL elementIsTextField = [node isKindOfClass:[DOMHTMLInputElement class]] && [(DOMHTMLInputElement*)node _isTextField];
720     BOOL elementIsTextArea = [node isKindOfClass:[DOMHTMLTextAreaElement class]];
721     if (_private->UIDelegate && !elementIsTextField && !elementIsTextArea) {
722         id cd = _private->UIDelegate;
723         
724         if ([cd respondsToSelector:@selector(webView:contextMenuItemsForElement:defaultMenuItems:)]) {
725             menuItems = [cd webView:self contextMenuItemsForElement:element defaultMenuItems:defaultMenuItems];
726
727             // Versions of Mail compiled with older WebKits will end up without three context menu items, though
728             // with the separators between them. Here we check for that problem and reinsert the three missing
729             // items. This shouldn't affect any clients other than Mail since the tags for the three items
730             // were not public API. We can remove this code when we no longer support previously-built versions
731             // of Mail on Tiger. See 4498606 for more details.
732             if ([menuItems count] && ([[defaultMenuItems objectAtIndex:0] tag] == WebMenuItemTagSearchInSpotlight) && ([[menuItems objectAtIndex:0] isSeparatorItem])) {
733                 ASSERT([[menuItems objectAtIndex:1] isSeparatorItem]);
734                 ASSERT([[defaultMenuItems objectAtIndex:1] tag] == WebMenuItemTagSearchWeb);
735                 ASSERT([[defaultMenuItems objectAtIndex:2] isSeparatorItem]);
736                 ASSERT([[defaultMenuItems objectAtIndex:3] tag] == WebMenuItemTagLookUpInDictionary);
737                 ASSERT([[defaultMenuItems objectAtIndex:4] isSeparatorItem]);
738                 NSMutableArray *mutableMenuItems = [NSMutableArray arrayWithArray:menuItems];
739                 [mutableMenuItems insertObject:[defaultMenuItems objectAtIndex:0] atIndex:0];
740                 [mutableMenuItems insertObject:[defaultMenuItems objectAtIndex:1] atIndex:1];
741                 [mutableMenuItems insertObject:[defaultMenuItems objectAtIndex:3] atIndex:3];
742                 menuItems = mutableMenuItems;
743             }
744         }
745     } 
746
747     if (menuItems && [menuItems count] > 0) {
748         menu = [[[NSMenu alloc] init] autorelease];
749
750         for (i=0; i<[menuItems count]; i++) {
751             [menu addItem:[menuItems objectAtIndex:i]];
752         }
753     }
754
755     // optionally add the Inspect Element menu item it if preference is set or in debug builds
756     // and only showing the menu item if we are working with a WebHTMLView
757     WebFrame *webFrame = [element objectForKey:WebElementFrameKey];
758     if ([WebView _developerExtrasEnabled] && [[[webFrame frameView] documentView] isKindOfClass:[WebHTMLView class]]) {
759         if (!menu)
760             menu = [[[NSMenu alloc] init] autorelease];
761         else if ([menu numberOfItems])
762             [menu addItem:[NSMenuItem separatorItem]];
763         NSMenuItem *menuItem = [[[NSMenuItem alloc] init] autorelease];
764         [menuItem setAction:@selector(_inspectElement:)];
765         [menuItem setTitle:UI_STRING("Inspect Element", "Inspect Element context menu item")];
766         [menuItem setRepresentedObject:element];
767         [menu addItem:menuItem];
768     }
769
770     return menu;
771 }
772
773 - (void)_mouseDidMoveOverElement:(NSDictionary *)dictionary modifierFlags:(WebNSUInteger)modifierFlags
774 {
775     // When the mouse isn't over this view at all, we'll get called with a dictionary of nil over
776     // and over again. So it's a good idea to catch that here and not send multiple calls to the delegate
777     // for that case.
778     
779     if (dictionary && _private->lastElementWasNonNil) {
780         [[self _UIDelegateForwarder] webView:self mouseDidMoveOverElement:dictionary modifierFlags:modifierFlags];
781     }
782     _private->lastElementWasNonNil = dictionary != nil;
783 }
784
785 - (void)_goToItem:(WebHistoryItem *)item withLoadType:(WebFrameLoadType)type
786 {
787     // We never go back/forward on a per-frame basis, so the target must be the main frame
788     //ASSERT([item target] == nil || [self _findFrameNamed:[item target]] == [self mainFrame]);
789
790     // abort any current load if we're going back/forward
791     [[self mainFrame] stopLoading];
792     [[self mainFrame] _goToItem:item withLoadType:type];
793 }
794
795 - (void)_loadBackForwardListFromOtherView:(WebView *)otherView
796 {
797     // It turns out the right combination of behavior is done with the back/forward load
798     // type.  (See behavior matrix at the top of WebFramePrivate.)  So we copy all the items
799     // in the back forward list, and go to the current one.
800
801     WebBackForwardList *bfList = [self backForwardList];
802     ASSERT(![bfList currentItem]); // destination list should be empty
803
804     WebBackForwardList *otherBFList = [otherView backForwardList];
805     if (![otherBFList currentItem]) {
806         return; // empty back forward list, bail
807     }
808
809     WebHistoryItem *newItemToGoTo = nil;
810     int lastItemIndex = [otherBFList forwardListCount];
811     int i;
812     for (i = -[otherBFList backListCount]; i <= lastItemIndex; i++) {
813         if (i == 0) {
814             // If this item is showing , save away its current scroll and form state,
815             // since that might have changed since loading and it is normally not saved
816             // until we leave that page.
817             [[otherView mainFrame] _saveDocumentAndScrollState];
818         }
819         WebHistoryItem *newItem = [[otherBFList itemAtIndex:i] copy];
820         [bfList addItem:newItem];
821         if (i == 0) {
822             newItemToGoTo = newItem;
823         }
824     }
825     
826     [self _goToItem:newItemToGoTo withLoadType:WebFrameLoadTypeIndexedBackForward];
827 }
828
829 - (void)_setFormDelegate: (id<WebFormDelegate>)delegate
830 {
831     _private->formDelegate = delegate;
832 }
833
834 - (id<WebFormDelegate>)_formDelegate
835 {
836     if (!_private->formDelegate) {
837         // create lazily, to give the client a chance to set one before we bother to alloc the shared one
838         _private->formDelegate = [WebFormDelegate _sharedWebFormDelegate];
839     }
840     return _private->formDelegate;
841 }
842
843 - (WebCoreSettings *)_settings
844 {
845     return _private->settings;
846 }
847
848 - (void)_updateWebCoreSettingsFromPreferences:(WebPreferences *)preferences
849 {
850     [_private->settings setCursiveFontFamily:[preferences cursiveFontFamily]];
851     [_private->settings setDefaultFixedFontSize:[preferences defaultFixedFontSize]];
852     [_private->settings setDefaultFontSize:[preferences defaultFontSize]];
853     [_private->settings setDefaultTextEncoding:[preferences defaultTextEncodingName]];
854     [_private->settings setFantasyFontFamily:[preferences fantasyFontFamily]];
855     [_private->settings setFixedFontFamily:[preferences fixedFontFamily]];
856     [_private->settings setJavaEnabled:[preferences isJavaEnabled]];
857     [_private->settings setJavaScriptEnabled:[preferences isJavaScriptEnabled]];
858     [_private->settings setJavaScriptCanOpenWindowsAutomatically:[preferences javaScriptCanOpenWindowsAutomatically]];
859     [_private->settings setMinimumFontSize:[preferences minimumFontSize]];
860     [_private->settings setMinimumLogicalFontSize:[preferences minimumLogicalFontSize]];
861     [_private->settings setPluginsEnabled:[preferences arePlugInsEnabled]];
862     [_private->settings setPrivateBrowsingEnabled:[preferences privateBrowsingEnabled]];
863     [_private->settings setSansSerifFontFamily:[preferences sansSerifFontFamily]];
864     [_private->settings setSerifFontFamily:[preferences serifFontFamily]];
865     [_private->settings setStandardFontFamily:[preferences standardFontFamily]];
866     [_private->settings setWillLoadImagesAutomatically:[preferences loadsImagesAutomatically]];
867
868     if ([preferences userStyleSheetEnabled]) {
869         [_private->settings setUserStyleSheetLocation:[[preferences userStyleSheetLocation] _web_originalDataAsString]];
870     } else {
871         [_private->settings setUserStyleSheetLocation:@""];
872     }
873     [_private->settings setShouldPrintBackgrounds:[preferences shouldPrintBackgrounds]];
874     [_private->settings setTextAreasAreResizable:[preferences textAreasAreResizable]];
875 }
876
877 - (void)_preferencesChangedNotification: (NSNotification *)notification
878 {
879     WebPreferences *preferences = (WebPreferences *)[notification object];
880     
881     ASSERT(preferences == [self preferences]);
882     if (!_private->userAgentOverridden) {
883         [_private->userAgent release];
884         _private->userAgent = nil;
885     }
886     [self _updateWebCoreSettingsFromPreferences: preferences];
887 }
888
889 - _frameLoadDelegateForwarder
890 {
891     if (!_private->frameLoadDelegateForwarder)
892         _private->frameLoadDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget: [self frameLoadDelegate]  defaultTarget: [WebDefaultFrameLoadDelegate sharedFrameLoadDelegate] templateClass: [WebDefaultFrameLoadDelegate class]];
893     return _private->frameLoadDelegateForwarder;
894 }
895
896 - _resourceLoadDelegateForwarder
897 {
898     if (!_private->resourceProgressDelegateForwarder)
899         _private->resourceProgressDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget: [self resourceLoadDelegate] defaultTarget: [WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] templateClass: [WebDefaultResourceLoadDelegate class]];
900     return _private->resourceProgressDelegateForwarder;
901 }
902
903 - (void)_cacheResourceLoadDelegateImplementations
904 {
905     WebResourceDelegateImplementationCache *cache = &_private->resourceLoadDelegateImplementations;
906     id delegate = [self resourceLoadDelegate];
907
908     cache->delegateImplementsDidCancelAuthenticationChallenge = [delegate respondsToSelector:@selector(webView:resource:didCancelAuthenticationChallenge:fromDataSource:)];
909     cache->delegateImplementsDidReceiveAuthenticationChallenge = [delegate respondsToSelector:@selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:)];
910     cache->delegateImplementsDidFinishLoadingFromDataSource = [delegate respondsToSelector:@selector(webView:resource:didFinishLoadingFromDataSource:)];
911     cache->delegateImplementsDidReceiveContentLength = [delegate respondsToSelector:@selector(webView:resource:didReceiveContentLength:fromDataSource:)];
912     cache->delegateImplementsDidReceiveResponse = [delegate respondsToSelector:@selector(webView:resource:didReceiveResponse:fromDataSource:)];
913     cache->delegateImplementsWillSendRequest = [delegate respondsToSelector:@selector(webView:resource:willSendRequest:redirectResponse:fromDataSource:)];
914     cache->delegateImplementsIdentifierForRequest = [delegate respondsToSelector:@selector(webView:identifierForInitialRequest:fromDataSource:)];
915 }
916
917 - (WebResourceDelegateImplementationCache)_resourceLoadDelegateImplementations
918 {
919     return _private->resourceLoadDelegateImplementations;
920 }
921
922 - _policyDelegateForwarder
923 {
924     if (!_private->policyDelegateForwarder)
925         _private->policyDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget: [self policyDelegate] defaultTarget: [WebDefaultPolicyDelegate sharedPolicyDelegate] templateClass: [WebDefaultPolicyDelegate class]];
926     return _private->policyDelegateForwarder;
927 }
928
929 - _UIDelegateForwarder
930 {
931     if (!_private->UIDelegateForwarder)
932         _private->UIDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget: [self UIDelegate] defaultTarget: [WebDefaultUIDelegate sharedUIDelegate] templateClass: [WebDefaultUIDelegate class]];
933     return _private->UIDelegateForwarder;
934 }
935
936 - _editingDelegateForwarder
937 {
938     // This can be called during window deallocation by QTMovieView in the QuickTime Cocoa Plug-in.
939     // Not sure if that is a bug or not.
940     if (!_private)
941         return nil;
942     if (!_private->editingDelegateForwarder)
943         _private->editingDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget: [self editingDelegate] defaultTarget: [WebDefaultEditingDelegate sharedEditingDelegate] templateClass: [WebDefaultEditingDelegate class]];
944     return _private->editingDelegateForwarder;
945 }
946
947 - _scriptDebugDelegateForwarder
948 {
949     if (!_private->scriptDebugDelegateForwarder)
950         _private->scriptDebugDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget: [self scriptDebugDelegate] defaultTarget: [WebDefaultScriptDebugDelegate sharedScriptDebugDelegate] templateClass: [WebDefaultScriptDebugDelegate class]];
951     return _private->scriptDebugDelegateForwarder;
952 }
953
954 - (void)_closeWindow
955 {
956     [[self _UIDelegateForwarder] webViewClose:self];
957 }
958
959 + (void)_unregisterViewClassAndRepresentationClassForMIMEType:(NSString *)MIMEType;
960 {
961     [[WebFrameView _viewTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType];
962     [[WebDataSource _repTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType];
963 }
964
965 + (void)_registerViewClass:(Class)viewClass representationClass:(Class)representationClass forURLScheme:(NSString *)URLScheme;
966 {
967     NSString *MIMEType = [self _generatedMIMETypeForURLScheme:URLScheme];
968     [self registerViewClass:viewClass representationClass:representationClass forMIMEType:MIMEType];
969
970     // This is used to make _representationExistsForURLScheme faster.
971     // Without this set, we'd have to create the MIME type each time.
972     if (schemesWithRepresentationsSet == nil) {
973         schemesWithRepresentationsSet = [[NSMutableSet alloc] init];
974     }
975     [schemesWithRepresentationsSet addObject:[[[URLScheme lowercaseString] copy] autorelease]];
976 }
977
978 + (NSString *)_generatedMIMETypeForURLScheme:(NSString *)URLScheme
979 {
980     return [@"x-apple-web-kit/" stringByAppendingString:[URLScheme lowercaseString]];
981 }
982
983 + (BOOL)_representationExistsForURLScheme:(NSString *)URLScheme
984 {
985     return [schemesWithRepresentationsSet containsObject:[URLScheme lowercaseString]];
986 }
987
988 + (BOOL)_canHandleRequest:(NSURLRequest *)request
989 {
990     if ([NSURLConnection canHandleRequest:request]) {
991         return YES;
992     }
993     
994     // We're always willing to load alternate content for unreachable URLs
995     if ([request _webDataRequestUnreachableURL]) {
996         return YES;
997     }
998
999     return [self _representationExistsForURLScheme:[[request URL] scheme]];
1000 }
1001
1002 + (NSString *)_decodeData:(NSData *)data
1003 {
1004     return [WebCoreEncodings decodeData:data];
1005 }
1006
1007 - (void)_pushPerformingProgrammaticFocus
1008 {
1009     _private->programmaticFocusCount++;
1010 }
1011
1012 - (void)_popPerformingProgrammaticFocus
1013 {
1014     _private->programmaticFocusCount--;
1015 }
1016
1017 - (BOOL)_isPerformingProgrammaticFocus
1018 {
1019     return _private->programmaticFocusCount != 0;
1020 }
1021
1022 #define UnknownTotalBytes -1
1023 #define WebProgressItemDefaultEstimatedLength 1024*16
1024
1025 - (void)_didChangeValueForKey: (NSString *)key
1026 {
1027     LOG (Bindings, "calling didChangeValueForKey: %@", key);
1028     [self didChangeValueForKey: key];
1029 }
1030
1031 - (void)_willChangeValueForKey: (NSString *)key
1032 {
1033     LOG (Bindings, "calling willChangeValueForKey: %@", key);
1034     [self willChangeValueForKey: key];
1035 }
1036
1037 // Always start progress at INITIAL_PROGRESS_VALUE. This helps provide feedback as 
1038 // soon as a load starts.
1039 #define INITIAL_PROGRESS_VALUE 0.1
1040 // Similarly, always leave space at the end. This helps show the user that we're not done
1041 // until we're done.
1042 #define FINAL_PROGRESS_VALUE 1.0 - INITIAL_PROGRESS_VALUE
1043
1044 - (void)_resetProgress
1045 {
1046     [_private->progressItems release];
1047     _private->progressItems = nil;
1048     _private->totalPageAndResourceBytesToLoad = 0;
1049     _private->totalBytesReceived = 0;
1050     _private->progressValue = 0;
1051     _private->lastNotifiedProgressValue = 0;
1052     _private->lastNotifiedProgressTime = 0;
1053     _private->finalProgressChangedSent = NO;
1054     _private->numProgressTrackedFrames = 0;
1055     [_private->originatingProgressFrame release];
1056     _private->originatingProgressFrame = nil;
1057 }
1058 - (void)_progressStarted:(WebFrame *)frame
1059 {
1060     LOG (Progress, "frame %p(%@), _private->numProgressTrackedFrames %d, _private->originatingProgressFrame %p", frame, [frame name], _private->numProgressTrackedFrames, _private->originatingProgressFrame);
1061     [self _willChangeValueForKey: @"estimatedProgress"];
1062     if (_private->numProgressTrackedFrames == 0 || _private->originatingProgressFrame == frame){
1063         [self _resetProgress];
1064         _private->progressValue = INITIAL_PROGRESS_VALUE;
1065         _private->originatingProgressFrame = [frame retain];
1066         [[NSNotificationCenter defaultCenter] postNotificationName:WebViewProgressStartedNotification object:self];
1067     }
1068     _private->numProgressTrackedFrames++;
1069     [self _didChangeValueForKey: @"estimatedProgress"];
1070 }
1071
1072 - (void)_finalProgressComplete
1073 {
1074     LOG (Progress, "");
1075
1076     // Before resetting progress value be sure to send client a least one notification
1077     // with final progress value.
1078     if (!_private->finalProgressChangedSent) {
1079         _private->progressValue = 1;
1080         [[NSNotificationCenter defaultCenter] postNotificationName:WebViewProgressEstimateChangedNotification object:self];
1081     }
1082     
1083     [self _resetProgress];
1084     
1085     [self setMainFrameDocumentReady:YES];   // make sure this is turned on at this point
1086     [[NSNotificationCenter defaultCenter] postNotificationName:WebViewProgressFinishedNotification object:self];
1087 }
1088
1089 - (void)_progressCompleted:(WebFrame *)frame
1090 {    
1091     LOG (Progress, "frame %p(%@), _private->numProgressTrackedFrames %d, _private->originatingProgressFrame %p", frame, [frame name], _private->numProgressTrackedFrames, _private->originatingProgressFrame);
1092
1093     if (_private->numProgressTrackedFrames <= 0)
1094         return;
1095
1096     [self _willChangeValueForKey: @"estimatedProgress"];
1097
1098     _private->numProgressTrackedFrames--;
1099     if (_private->numProgressTrackedFrames == 0 ||
1100         (frame == _private->originatingProgressFrame && _private->numProgressTrackedFrames != 0)){
1101         [self _finalProgressComplete];
1102     }
1103     [self _didChangeValueForKey: @"estimatedProgress"];
1104 }
1105
1106 - (void)_incrementProgressForIdentifier:(id)identifier response:(NSURLResponse *)response;
1107 {
1108     if (!identifier)
1109         return;
1110
1111     LOG (Progress, "_private->numProgressTrackedFrames %d, _private->originatingProgressFrame %p", _private->numProgressTrackedFrames, _private->originatingProgressFrame);
1112     
1113     if (_private->numProgressTrackedFrames <= 0)
1114         return;
1115         
1116     WebProgressItem *item = [[WebProgressItem alloc] init];
1117
1118     if (!item)
1119         return;
1120
1121     long long length = [response expectedContentLength];
1122     if (length < 0){
1123         length = WebProgressItemDefaultEstimatedLength;
1124     }
1125     item->estimatedLength = length;
1126     _private->totalPageAndResourceBytesToLoad += length;
1127     
1128     if (!_private->progressItems)
1129         _private->progressItems = [[NSMutableDictionary alloc] init];
1130         
1131     [_private->progressItems _webkit_setObject:item forUncopiedKey:identifier];
1132     [item release];
1133 }
1134
1135 - (void)_incrementProgressForIdentifier:(id)identifier data:(NSData *)data
1136 {
1137     if (!identifier)
1138         return;
1139
1140     WebProgressItem *item = [_private->progressItems objectForKey:identifier];
1141
1142     if (!item)
1143         return;
1144
1145     [self _willChangeValueForKey: @"estimatedProgress"];
1146
1147     unsigned bytesReceived = [data length];
1148     double increment, percentOfRemainingBytes;
1149     long long remainingBytes, estimatedBytesForPendingRequests;
1150
1151     item->bytesReceived += bytesReceived;
1152     if (item->bytesReceived > item->estimatedLength){
1153         _private->totalPageAndResourceBytesToLoad += ((item->bytesReceived*2) - item->estimatedLength);
1154         item->estimatedLength = item->bytesReceived*2;
1155     }
1156     
1157     int numPendingOrLoadingRequests = [_private->originatingProgressFrame _numPendingOrLoadingRequests:YES];
1158     estimatedBytesForPendingRequests = WebProgressItemDefaultEstimatedLength * numPendingOrLoadingRequests;
1159     remainingBytes = ((_private->totalPageAndResourceBytesToLoad + estimatedBytesForPendingRequests) - _private->totalBytesReceived);
1160     percentOfRemainingBytes = (double)bytesReceived / (double)remainingBytes;
1161
1162     // Treat the first layout as the half-way point.
1163     double maxProgressValue = [_private->originatingProgressFrame _firstLayoutDone]
1164         ? FINAL_PROGRESS_VALUE
1165         : .5;
1166     increment = (maxProgressValue - _private->progressValue) * percentOfRemainingBytes;
1167     _private->progressValue += increment;
1168     if (_private->progressValue > maxProgressValue)
1169         _private->progressValue = maxProgressValue;
1170     ASSERT(_private->progressValue >= INITIAL_PROGRESS_VALUE);
1171
1172     _private->totalBytesReceived += bytesReceived;
1173
1174     double now = CFAbsoluteTimeGetCurrent();
1175     double notifiedProgressTimeDelta = now - _private->lastNotifiedProgressTime;
1176     
1177     LOG (Progress, "_private->progressValue %g, _private->numProgressTrackedFrames %d", _private->progressValue, _private->numProgressTrackedFrames);
1178     double notificationProgressDelta = _private->progressValue - _private->lastNotifiedProgressValue;
1179     if ((notificationProgressDelta >= _private->progressNotificationInterval ||
1180             notifiedProgressTimeDelta >= _private->progressNotificationTimeInterval) &&
1181             _private->numProgressTrackedFrames > 0) {
1182         if (!_private->finalProgressChangedSent) {
1183             if (_private->progressValue == 1)
1184                 _private->finalProgressChangedSent = YES;
1185             [[NSNotificationCenter defaultCenter] postNotificationName:WebViewProgressEstimateChangedNotification object:self];
1186             _private->lastNotifiedProgressValue = _private->progressValue;
1187             _private->lastNotifiedProgressTime = now;
1188         }
1189     }
1190
1191     [self _didChangeValueForKey: @"estimatedProgress"];
1192 }
1193
1194 - (void)_completeProgressForIdentifier:(id)identifier
1195 {
1196     WebProgressItem *item = [_private->progressItems objectForKey:identifier];
1197
1198     if (!item)
1199         return;
1200         
1201     // Adjust the total expected bytes to account for any overage/underage.
1202     long long delta = item->bytesReceived - item->estimatedLength;
1203     _private->totalPageAndResourceBytesToLoad += delta;
1204     item->estimatedLength = item->bytesReceived;
1205 }
1206
1207 // Required to prevent automatic observer notifications.
1208 + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key {
1209     return NO;
1210 }
1211
1212 - (NSArray *)_declaredKeys {
1213     static NSArray *declaredKeys = nil;
1214     
1215     if (!declaredKeys) {
1216         declaredKeys = [[NSArray alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey, _WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, _WebMainFrameDocumentKey, nil];
1217     }
1218
1219     return declaredKeys;
1220 }
1221
1222 - (void)setObservationInfo:(void *)info
1223 {
1224     _private->observationInfo = info;
1225 }
1226
1227 - (void *)observationInfo
1228 {
1229     return _private->observationInfo;
1230 }
1231
1232 - (void)_willChangeBackForwardKeys
1233 {
1234     [self _willChangeValueForKey: _WebCanGoBackKey];
1235     [self _willChangeValueForKey: _WebCanGoForwardKey];
1236 }
1237
1238 - (void)_didChangeBackForwardKeys
1239 {
1240     [self _didChangeValueForKey: _WebCanGoBackKey];
1241     [self _didChangeValueForKey: _WebCanGoForwardKey];
1242 }
1243
1244 - (void)_didStartProvisionalLoadForFrame:(WebFrame *)frame
1245 {
1246     [self _willChangeBackForwardKeys];
1247     if (frame == [self mainFrame]){
1248         // Force an observer update by sending a will/did.
1249         [self _willChangeValueForKey: _WebIsLoadingKey];
1250         [self _didChangeValueForKey: _WebIsLoadingKey];
1251
1252         [self _willChangeValueForKey: _WebMainFrameURLKey];
1253     }
1254     [NSApp setWindowsNeedUpdate:YES];
1255 }
1256
1257 - (void)_didCommitLoadForFrame:(WebFrame *)frame
1258 {
1259     if (frame == [self mainFrame]){
1260         [self _didChangeValueForKey: _WebMainFrameURLKey];
1261     }
1262     [NSApp setWindowsNeedUpdate:YES];
1263 }
1264
1265 - (void)_didFinishLoadForFrame:(WebFrame *)frame
1266 {
1267     [self _didChangeBackForwardKeys];
1268     if (frame == [self mainFrame]){
1269         // Force an observer update by sending a will/did.
1270         [self _willChangeValueForKey: _WebIsLoadingKey];
1271         [self _didChangeValueForKey: _WebIsLoadingKey];
1272     }
1273     [NSApp setWindowsNeedUpdate:YES];
1274 }
1275
1276 - (void)_didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
1277 {
1278     [self _didChangeBackForwardKeys];
1279     if (frame == [self mainFrame]){
1280         // Force an observer update by sending a will/did.
1281         [self _willChangeValueForKey: _WebIsLoadingKey];
1282         [self _didChangeValueForKey: _WebIsLoadingKey];
1283     }
1284     [NSApp setWindowsNeedUpdate:YES];
1285 }
1286
1287 - (void)_didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
1288 {
1289     [self _didChangeBackForwardKeys];
1290     if (frame == [self mainFrame]){
1291         // Force an observer update by sending a will/did.
1292         [self _willChangeValueForKey: _WebIsLoadingKey];
1293         [self _didChangeValueForKey: _WebIsLoadingKey];
1294         
1295         [self _didChangeValueForKey: _WebMainFrameURLKey];
1296     }
1297     [NSApp setWindowsNeedUpdate:YES];
1298 }
1299
1300 - (void)_reloadForPluginChanges
1301 {
1302     [[self mainFrame] _reloadForPluginChanges];
1303 }
1304
1305 - (NSCachedURLResponse *)_cachedResponseForURL:(NSURL *)URL
1306 {
1307     NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:URL];
1308     [request _web_setHTTPUserAgent:[self userAgentForURL:URL]];
1309     NSCachedURLResponse *cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:request];
1310     [request release];
1311     return cachedResponse;
1312 }
1313
1314 - (void)_writeImageForElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
1315 {
1316     NSURL *linkURL = [element objectForKey:WebElementLinkURLKey];
1317     DOMElement *domElement = [element objectForKey:WebElementDOMNodeKey];
1318     [pasteboard _web_writeImage:(NSImage *)(domElement ? nil : [element objectForKey:WebElementImageKey])
1319                         element:domElement
1320                             URL:linkURL ? linkURL : (NSURL *)[element objectForKey:WebElementImageURLKey]
1321                           title:[element objectForKey:WebElementImageAltStringKey] 
1322                         archive:[[element objectForKey:WebElementDOMNodeKey] webArchive]
1323                           types:types];
1324 }
1325
1326 - (void)_writeLinkElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
1327 {
1328     [pasteboard _web_writeURL:[element objectForKey:WebElementLinkURLKey]
1329                      andTitle:[element objectForKey:WebElementLinkLabelKey]
1330                         types:types];
1331 }
1332
1333 - (void)_setInitiatedDrag:(BOOL)initiatedDrag
1334 {
1335     _private->initiatedDrag = initiatedDrag;
1336 }
1337
1338 #define DASHBOARD_CONTROL_LABEL @"control"
1339
1340 - (void)_addScrollerDashboardRegions:(NSMutableDictionary *)regions from:(NSArray *)views
1341 {
1342     // Add scroller regions for NSScroller and KWQScrollBar
1343     int i, count = [views count];
1344     
1345     for (i = 0; i < count; i++) {
1346         NSView *aView = [views objectAtIndex:i];
1347         
1348         if ([aView isKindOfClass:[NSScroller class]] ||
1349             [aView isKindOfClass:NSClassFromString (@"KWQScrollBar")]) {
1350             NSRect bounds = [aView bounds];
1351             NSRect adjustedBounds;
1352             adjustedBounds.origin = [self convertPoint:bounds.origin fromView:aView];
1353             adjustedBounds.origin.y = [self bounds].size.height - adjustedBounds.origin.y;
1354             
1355             // AppKit has horrible hack of placing absent scrollers at -100,-100
1356             if (adjustedBounds.origin.y == -100)
1357                 continue;
1358             adjustedBounds.size = bounds.size;
1359             NSRect clip = [aView visibleRect];
1360             NSRect adjustedClip;
1361             adjustedClip.origin = [self convertPoint:clip.origin fromView:aView];
1362             adjustedClip.origin.y = [self bounds].size.height - adjustedClip.origin.y;
1363             adjustedClip.size = clip.size;
1364             WebDashboardRegion *aRegion = 
1365                         [[[WebDashboardRegion alloc] initWithRect:adjustedBounds 
1366                                     clip:adjustedClip type:WebDashboardRegionTypeScrollerRectangle] autorelease];
1367             NSMutableArray *scrollerRegions;
1368             scrollerRegions = [regions objectForKey:DASHBOARD_CONTROL_LABEL];
1369             if (!scrollerRegions) {
1370                 scrollerRegions = [NSMutableArray array];
1371                 [regions setObject:scrollerRegions forKey:DASHBOARD_CONTROL_LABEL];
1372             }
1373             [scrollerRegions addObject:aRegion];
1374         }
1375         [self _addScrollerDashboardRegions:regions from:[aView subviews]];
1376     }
1377 }
1378
1379 - (void)_addScrollerDashboardRegions:(NSMutableDictionary *)regions
1380 {
1381     [self _addScrollerDashboardRegions:regions from:[self subviews]];
1382 }
1383
1384 - (NSDictionary *)_dashboardRegions
1385 {
1386     // Only return regions from main frame.
1387     NSMutableDictionary *regions = [[[self mainFrame] _bridge] dashboardRegions];
1388     [self _addScrollerDashboardRegions:regions];
1389     return regions;
1390 }
1391
1392 - (void)_setDashboardBehavior:(WebDashboardBehavior)behavior to:(BOOL)flag;
1393 {
1394     switch (behavior) {
1395         case WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows: {
1396             _private->dashboardBehaviorAlwaysSendMouseEventsToAllWindows = flag;
1397             break;
1398         }
1399         case WebDashboardBehaviorAlwaysSendActiveNullEventsToPlugIns: {
1400             _private->dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns = flag;
1401             break;
1402         }
1403         case WebDashboardBehaviorAlwaysAcceptsFirstMouse: {
1404             _private->dashboardBehaviorAlwaysAcceptsFirstMouse = flag;
1405             break;
1406         }
1407         case WebDashboardBehaviorAllowWheelScrolling: {
1408             _private->dashboardBehaviorAllowWheelScrolling = flag;
1409             break;
1410         }
1411     }
1412 }
1413
1414 - (BOOL)_dashboardBehavior:(WebDashboardBehavior)behavior
1415 {
1416     switch (behavior) {
1417         case WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows: {
1418             return _private->dashboardBehaviorAlwaysSendMouseEventsToAllWindows;
1419         }
1420         case WebDashboardBehaviorAlwaysSendActiveNullEventsToPlugIns: {
1421             return _private->dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns;
1422         }
1423         case WebDashboardBehaviorAlwaysAcceptsFirstMouse: {
1424             return _private->dashboardBehaviorAlwaysAcceptsFirstMouse;
1425         }
1426         case WebDashboardBehaviorAllowWheelScrolling: {
1427             return _private->dashboardBehaviorAllowWheelScrolling;
1428         }
1429     }
1430     return NO;
1431 }
1432
1433 - (void)handleAuthenticationForResource:(id)identifier challenge:(NSURLAuthenticationChallenge *)challenge fromDataSource:(WebDataSource *)dataSource
1434 {
1435     [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:self resource:identifier didReceiveAuthenticationChallenge:challenge fromDataSource:dataSource];
1436 }
1437
1438 + (void)_setShouldUseFontSmoothing:(BOOL)f
1439 {
1440     WebCoreSetShouldUseFontSmoothing(f);
1441 }
1442
1443 + (BOOL)_shouldUseFontSmoothing
1444 {
1445     return WebCoreShouldUseFontSmoothing();
1446 }
1447
1448 + (NSString *)_minimumRequiredSafariBuildNumber
1449 {
1450     return @"420+";
1451 }
1452
1453 - (void)setAlwaysShowVerticalScroller:(BOOL)flag
1454 {
1455     WebDynamicScrollBarsView *scrollview = (WebDynamicScrollBarsView *)[[[self mainFrame] frameView] _scrollView];
1456     if (flag) {
1457         [scrollview setVerticalScrollingMode:WebCoreScrollBarAlwaysOn];
1458         [scrollview setVerticalScrollingModeLocked:YES];
1459     } else {
1460         [scrollview setVerticalScrollingModeLocked:NO];
1461         [scrollview setVerticalScrollingMode:WebCoreScrollBarAuto];
1462     }
1463 }
1464
1465 - (BOOL)alwaysShowVerticalScroller
1466 {
1467     WebDynamicScrollBarsView *scrollview = (WebDynamicScrollBarsView *)[[[self mainFrame] frameView] _scrollView];
1468     return [scrollview verticalScrollingModeLocked] && [scrollview verticalScrollingMode] == WebCoreScrollBarAlwaysOn;
1469 }
1470
1471 - (void)setAlwaysShowHorizontalScroller:(BOOL)flag
1472 {
1473     WebDynamicScrollBarsView *scrollview = (WebDynamicScrollBarsView *)[[[self mainFrame] frameView] _scrollView];
1474     if (flag) {
1475         [scrollview setHorizontalScrollingMode:WebCoreScrollBarAlwaysOn];
1476         [scrollview setHorizontalScrollingModeLocked:YES];
1477     } else {
1478         [scrollview setHorizontalScrollingModeLocked:NO];
1479         [scrollview setHorizontalScrollingMode:WebCoreScrollBarAuto];
1480     }
1481 }
1482
1483 - (void)setProhibitsMainFrameScrolling:(BOOL)prohibits
1484 {
1485     [[[self mainFrame] _bridge] setProhibitsScrolling:YES];
1486 }
1487
1488 - (BOOL)alwaysShowHorizontalScroller
1489 {
1490     WebDynamicScrollBarsView *scrollview = (WebDynamicScrollBarsView *)[[[self mainFrame] frameView] _scrollView];
1491     return [scrollview horizontalScrollingModeLocked] && [scrollview horizontalScrollingMode] == WebCoreScrollBarAlwaysOn;
1492 }
1493
1494 - (void)_setInViewSourceMode:(BOOL)flag
1495 {
1496     [[[self mainFrame] _bridge] setInViewSourceMode:flag];
1497 }
1498
1499 - (BOOL)_inViewSourceMode
1500 {
1501     return [[[self mainFrame] _bridge] inViewSourceMode];
1502 }
1503
1504 - (void)_setAdditionalWebPlugInPaths:(NSArray *)newPaths
1505 {
1506     if (!_private->pluginDatabase)
1507         _private->pluginDatabase = [[WebPluginDatabase alloc] init];
1508         
1509     [_private->pluginDatabase setPlugInPaths:newPaths];
1510     [_private->pluginDatabase refresh];
1511 }
1512
1513 - (void)_attachScriptDebuggerToAllFrames
1514 {
1515     WebFrame *frame = [self mainFrame];
1516     do {
1517         [frame _attachScriptDebugger];
1518         frame = [frame _nextFrameWithWrap:NO];
1519     } while (frame);
1520 }
1521
1522 - (void)_detachScriptDebuggerFromAllFrames
1523 {
1524     WebFrame *frame = [self mainFrame];
1525     do {
1526         [frame _detachScriptDebugger];
1527         frame = [frame _nextFrameWithWrap:NO];
1528     } while (frame);
1529 }
1530
1531 @end
1532
1533
1534 @implementation _WebSafeForwarder
1535
1536 - initWithTarget: t defaultTarget: dt templateClass: (Class)aClass
1537 {
1538     self = [super init];
1539     if (!self)
1540         return nil;
1541     
1542     target = t; // Non retained.
1543     defaultTarget = dt;
1544     templateClass = aClass;
1545     return self;
1546 }
1547
1548
1549 // Used to send messages to delegates that implement informal protocols.
1550 + safeForwarderWithTarget: t defaultTarget: dt templateClass: (Class)aClass;
1551 {
1552     return [[[_WebSafeForwarder alloc] initWithTarget: t defaultTarget: dt templateClass: aClass] autorelease];
1553 }
1554
1555 #ifndef NDEBUG
1556 NSMutableDictionary *countInvocations;
1557 #endif
1558
1559 - (void)forwardInvocation:(NSInvocation *)anInvocation
1560 {
1561 #ifndef NDEBUG
1562     if (!countInvocations){
1563         countInvocations = [[NSMutableDictionary alloc] init];
1564     }
1565     NSNumber *count = [countInvocations objectForKey: NSStringFromSelector([anInvocation selector])];
1566     if (!count)
1567         count = [NSNumber numberWithInt: 1];
1568     else
1569         count = [NSNumber numberWithInt: [count intValue] + 1];
1570     [countInvocations setObject: count forKey: NSStringFromSelector([anInvocation selector])];
1571 #endif
1572     if ([target respondsToSelector: [anInvocation selector]])
1573         [anInvocation invokeWithTarget: target];
1574     else if ([defaultTarget respondsToSelector: [anInvocation selector]])
1575         [anInvocation invokeWithTarget: defaultTarget];
1576     // Do nothing quietly if method not implemented.
1577 }
1578
1579 - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
1580 {
1581     return [templateClass instanceMethodSignatureForSelector: aSelector];
1582 }
1583
1584 @end
1585
1586 @implementation WebView
1587
1588 #if REMOVE_SAFARI_DOM_TREE_DEBUG_ITEM
1589 // this prevents open source users from crashing when using the Show DOM Tree menu item in Safari
1590 // FIXME: remove this when it is no longer needed to prevent Safari from crashing
1591 +(void)initialize
1592 {
1593     static BOOL tooLate = NO;
1594     if (!tooLate) {
1595         if ([[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.Safari"] && [[NSUserDefaults standardUserDefaults] boolForKey:@"IncludeDebugMenu"])
1596             [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_finishedLaunching) name:NSApplicationDidFinishLaunchingNotification object:NSApp];
1597         tooLate = YES;
1598     }
1599 }
1600
1601 +(void)_finishedLaunching
1602 {
1603     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_removeDOMTreeMenuItem:) name:NSMenuDidAddItemNotification object:[NSApp mainMenu]];
1604     [[NSNotificationCenter defaultCenter] removeObserver:self name:NSApplicationDidFinishLaunchingNotification object:NSApp];
1605 }
1606
1607 +(void)_removeDOMTreeMenuItem:(NSNotification *)notification
1608 {
1609     NSMenu *debugMenu = [[[[NSApp mainMenu] itemArray] lastObject] submenu];
1610     NSMenuItem *domTree = [debugMenu itemWithTitle:@"Show DOM Tree"];
1611     if (domTree)
1612         [debugMenu removeItem:domTree];
1613     [[NSNotificationCenter defaultCenter] removeObserver:self name:NSMenuDidAddItemNotification object:[NSApp mainMenu]];
1614 }
1615 #endif
1616
1617 + (BOOL)canShowMIMEType:(NSString *)MIMEType
1618 {
1619     return [self _viewClass:nil andRepresentationClass:nil forMIMEType:MIMEType];
1620 }
1621
1622 - (WebBasePluginPackage *)_pluginForMIMEType:(NSString *)MIMEType
1623 {
1624     WebBasePluginPackage *pluginPackage = [[WebPluginDatabase installedPlugins] pluginForMIMEType:MIMEType];
1625     if (pluginPackage)
1626         return pluginPackage;
1627     
1628     if (_private->pluginDatabase)
1629         return [_private->pluginDatabase pluginForMIMEType:MIMEType];
1630     
1631     return nil;
1632 }
1633
1634 - (WebBasePluginPackage *)_pluginForExtension:(NSString *)extension
1635 {
1636     WebBasePluginPackage *pluginPackage = [[WebPluginDatabase installedPlugins] pluginForExtension:extension];
1637     if (pluginPackage)
1638         return pluginPackage;
1639     
1640     if (_private->pluginDatabase)
1641         return [_private->pluginDatabase pluginForExtension:extension];
1642     
1643     return nil;
1644 }
1645
1646 - (BOOL)_isMIMETypeRegisteredAsPlugin:(NSString *)MIMEType
1647 {
1648     if ([[WebPluginDatabase installedPlugins] isMIMETypeRegistered:MIMEType])
1649         return YES;
1650         
1651     if (_private->pluginDatabase && [_private->pluginDatabase isMIMETypeRegistered:MIMEType])
1652         return YES;
1653     
1654     return NO;
1655 }
1656
1657 + (BOOL)canShowMIMETypeAsHTML:(NSString *)MIMEType
1658 {
1659     return [WebFrameView _canShowMIMETypeAsHTML:MIMEType];
1660 }
1661
1662 + (NSArray *)MIMETypesShownAsHTML
1663 {
1664     NSMutableDictionary *viewTypes = [WebFrameView _viewTypesAllowImageTypeOmission:YES];
1665     NSEnumerator *enumerator = [viewTypes keyEnumerator];
1666     id key;
1667     NSMutableArray *array = [[[NSMutableArray alloc] init] autorelease];
1668     
1669     while ((key = [enumerator nextObject])) {
1670         if ([viewTypes objectForKey:key] == [WebHTMLView class])
1671             [array addObject:key];
1672     }
1673     
1674     return array;
1675 }
1676
1677 + (void)setMIMETypesShownAsHTML:(NSArray *)MIMETypes
1678 {
1679     NSMutableDictionary *viewTypes = [WebFrameView _viewTypesAllowImageTypeOmission:YES];
1680     NSEnumerator *enumerator = [viewTypes keyEnumerator];
1681     id key;
1682     while ((key = [enumerator nextObject])) {
1683         if ([viewTypes objectForKey:key] == [WebHTMLView class])
1684             [WebView _unregisterViewClassAndRepresentationClassForMIMEType:key];
1685     }
1686     
1687     int i, count = [MIMETypes count];
1688     for (i = 0; i < count; i++) {
1689         [WebView registerViewClass:[WebHTMLView class] 
1690                 representationClass:[WebHTMLRepresentation class] 
1691                 forMIMEType:[MIMETypes objectAtIndex:i]];
1692     }
1693 }
1694
1695 + (NSURL *)URLFromPasteboard:(NSPasteboard *)pasteboard
1696 {
1697     return [pasteboard _web_bestURL];
1698 }
1699
1700 + (NSString *)URLTitleFromPasteboard:(NSPasteboard *)pasteboard
1701 {
1702     return [pasteboard stringForType:WebURLNamePboardType];
1703 }
1704
1705 - (void)_registerDraggedTypes
1706 {
1707     NSArray *editableTypes = [WebHTMLView _insertablePasteboardTypes];
1708     NSArray *URLTypes = [NSPasteboard _web_dragTypesForURL];
1709     NSMutableSet *types = [[NSMutableSet alloc] initWithArray:editableTypes];
1710     [types addObjectsFromArray:URLTypes];
1711     [self registerForDraggedTypes:[types allObjects]];
1712     [types release];
1713 }
1714
1715 - (void)_commonInitializationWithFrameName:(NSString *)frameName groupName:(NSString *)groupName
1716 {
1717     _private->mainFrameDocumentReady = NO;
1718     _private->drawsBackground = YES;
1719     _private->smartInsertDeleteEnabled = YES;
1720
1721     NSRect f = [self frame];
1722     WebFrameView *frameView = [[WebFrameView alloc] initWithFrame: NSMakeRect(0,0,f.size.width,f.size.height)];
1723     [frameView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
1724     [self addSubview:frameView];
1725     [frameView release];
1726
1727     WebKitInitializeLoggingChannelsIfNecessary();
1728     _private->_pageBridge = [[WebPageBridge alloc] initWithMainFrameName:frameName webView:self frameView:frameView];
1729
1730     [self _addToAllWebViewsSet];
1731     [self setGroupName:groupName];
1732     
1733     // If there's already a next key view (e.g., from a nib), wire it up to our
1734     // contained frame view. In any case, wire our next key view up to the our
1735     // contained frame view. This works together with our becomeFirstResponder 
1736     // and setNextKeyView overrides.
1737     NSView *nextKeyView = [self nextKeyView];
1738     if (nextKeyView != nil && nextKeyView != frameView) {
1739         [frameView setNextKeyView:nextKeyView];
1740     }
1741     [super setNextKeyView:frameView];
1742
1743     ++WebViewCount;
1744
1745     [self _registerDraggedTypes];
1746
1747     // initialize WebScriptDebugServer here so listeners can register before any pages are loaded.
1748     if ([WebView _scriptDebuggerEnabled])
1749         [WebScriptDebugServer sharedScriptDebugServer];
1750
1751     // Update WebCore with preferences.  These values will either come from an archived WebPreferences,
1752     // or from the standard preferences, depending on whether this method was called from initWithCoder:
1753     // or initWithFrame, respectively.
1754     [self _updateWebCoreSettingsFromPreferences: [self preferences]];
1755     
1756     // Register to receive notifications whenever preference values change.
1757     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:)
1758                                                  name:WebPreferencesChangedNotification object:[self preferences]];
1759 }
1760
1761 - (id)initWithFrame:(NSRect)f
1762 {
1763     return [self initWithFrame:f frameName:nil groupName:nil];
1764 }
1765
1766 - (id)initWithFrame:(NSRect)f frameName:(NSString *)frameName groupName:(NSString *)groupName;
1767 {
1768     self = [super initWithFrame:f];
1769     if (!self)
1770         return nil;
1771
1772 #if ENABLE_WEBKIT_UNSET_DYLD_FRAMEWORK_PATH
1773     // DYLD_FRAMEWORK_PATH is used so Safari will load the development version of WebKit, which
1774     // may not work with other WebKit applications.  Unsetting DYLD_FRAMEWORK_PATH removes the
1775     // need for Safari to unset it to prevent it from being passed to applications it launches.
1776     // Unsetting it when a WebView is first created is as good a place as any.
1777     // See <http://bugzilla.opendarwin.org/show_bug.cgi?id=4286> for more details.
1778     if (getenv("WEBKIT_UNSET_DYLD_FRAMEWORK_PATH")) {
1779         unsetenv("DYLD_FRAMEWORK_PATH");
1780         unsetenv("WEBKIT_UNSET_DYLD_FRAMEWORK_PATH");
1781     }
1782 #endif
1783
1784     _private = [[WebViewPrivate alloc] init];
1785     [self _commonInitializationWithFrameName:frameName groupName:groupName];
1786     [self setMaintainsBackForwardList: YES];
1787     return self;
1788 }
1789
1790 - (id)initWithCoder:(NSCoder *)decoder
1791 {
1792     WebView *result = nil;
1793
1794 NS_DURING
1795
1796     NSString *frameName;
1797     NSString *groupName;
1798     WebPreferences *preferences;
1799     BOOL useBackForwardList;
1800
1801     result = [super initWithCoder:decoder];
1802     result->_private = [[WebViewPrivate alloc] init];
1803
1804     // We don't want any of the archived subviews. The subviews will always
1805     // be created in _commonInitializationFrameName:groupName:.
1806     [[result subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
1807
1808     if ([decoder allowsKeyedCoding]) {
1809         frameName = [decoder decodeObjectForKey:@"FrameName"];
1810         groupName = [decoder decodeObjectForKey:@"GroupName"];
1811         preferences = [decoder decodeObjectForKey:@"Preferences"];
1812         useBackForwardList = [decoder decodeBoolForKey:@"UseBackForwardList"];
1813     } else {
1814         int version;
1815         [decoder decodeValueOfObjCType:@encode(int) at:&version];
1816         frameName = [decoder decodeObject];
1817         groupName = [decoder decodeObject];
1818         preferences = [decoder decodeObject];
1819         if (version > 1)
1820             [decoder decodeValuesOfObjCTypes:"c", &useBackForwardList];
1821     }
1822
1823     if (![frameName isKindOfClass:[NSString class]])
1824         frameName = nil;
1825     if (![groupName isKindOfClass:[NSString class]])
1826         groupName = nil;
1827     if (![preferences isKindOfClass:[WebPreferences class]])
1828         preferences = nil;
1829
1830     LOG(Encoding, "FrameName = %@, GroupName = %@, useBackForwardList = %d\n", frameName, groupName, (int)useBackForwardList);
1831
1832     if (preferences)
1833         [result setPreferences:preferences];
1834     result->_private->useBackForwardList = useBackForwardList;
1835     [result _commonInitializationWithFrameName:frameName groupName:groupName];
1836
1837 NS_HANDLER
1838
1839     result = nil;
1840     [self release];
1841
1842 NS_ENDHANDLER
1843
1844     return result;
1845 }
1846
1847 - (void)encodeWithCoder:(NSCoder *)encoder
1848 {
1849     [super encodeWithCoder:encoder];
1850
1851     if ([encoder allowsKeyedCoding]) {
1852         [encoder encodeObject:[[self mainFrame] name] forKey:@"FrameName"];
1853         [encoder encodeObject:[self groupName] forKey:@"GroupName"];
1854         [encoder encodeObject:[self preferences] forKey:@"Preferences"];
1855         [encoder encodeBool:_private->useBackForwardList forKey:@"UseBackForwardList"];
1856     } else {
1857         int version = WebViewVersion;
1858         [encoder encodeValueOfObjCType:@encode(int) at:&version];
1859         [encoder encodeObject:[[self mainFrame] name]];
1860         [encoder encodeObject:[self groupName]];
1861         [encoder encodeObject:[self preferences]];
1862         [encoder encodeValuesOfObjCTypes:"c", &_private->useBackForwardList];
1863     }
1864
1865     LOG(Encoding, "FrameName = %@, GroupName = %@, useBackForwardList = %d\n", [[self mainFrame] name], [self groupName], (int)_private->useBackForwardList);
1866 }
1867
1868 - (void)dealloc
1869 {
1870     // call close to ensure we tear-down completly
1871     // this maintains our old behavior for existing applications
1872     [self _close];
1873
1874     --WebViewCount;
1875     
1876     [_private release];
1877     // [super dealloc] can end up dispatching against _private (3466082)
1878     _private = nil;
1879
1880     [super dealloc];
1881 }
1882
1883 - (void)finalize
1884 {
1885     ASSERT(_private->closed);
1886
1887     --WebViewCount;
1888
1889     [super finalize];
1890 }
1891
1892 - (void)close
1893 {
1894     [self _close];
1895 }
1896
1897 - (void)setShouldCloseWithWindow:(BOOL)close
1898 {
1899     _private->shouldCloseWithWindow = close;
1900 }
1901
1902 - (BOOL)shouldCloseWithWindow
1903 {
1904     return _private->shouldCloseWithWindow;
1905 }
1906
1907 - (void)viewWillMoveToWindow:(NSWindow *)window
1908 {
1909     // Don't do anything if we aren't initialized.  This happens
1910     // when decoding a WebView.
1911     if (_private) {
1912         if ([self window])
1913             [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowWillCloseNotification object:[self window]];
1914         if (window)
1915             [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillClose:) name:NSWindowWillCloseNotification object:window];
1916     }
1917 }
1918
1919 - (void)_windowWillClose:(NSNotification *)notification
1920 {
1921     if ([self shouldCloseWithWindow] && ([self window] == [self hostWindow] || ([self window] && ![self hostWindow]) || (![self window] && [self hostWindow])))
1922         [self _close];
1923 }
1924
1925 - (void)setPreferences:(WebPreferences *)prefs
1926 {
1927     if (_private->preferences != prefs) {
1928         [[NSNotificationCenter defaultCenter] removeObserver:self name:WebPreferencesChangedNotification object:[self preferences]];
1929         [WebPreferences _removeReferenceForIdentifier:[_private->preferences identifier]];
1930         [_private->preferences release];
1931         _private->preferences = [prefs retain];
1932         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:)
1933             name:WebPreferencesChangedNotification object:[self preferences]];
1934         [[NSNotificationCenter defaultCenter]
1935             postNotificationName:WebPreferencesChangedNotification object:prefs userInfo:nil];
1936     }
1937 }
1938
1939 - (WebPreferences *)preferences
1940 {
1941     return _private->preferences ? _private->preferences : [WebPreferences standardPreferences];
1942 }
1943
1944 - (void)setPreferencesIdentifier:(NSString *)anIdentifier
1945 {
1946     if (!_private->closed && ![anIdentifier isEqual:[[self preferences] identifier]]) {
1947         WebPreferences *prefs = [[WebPreferences alloc] initWithIdentifier:anIdentifier];
1948         [self setPreferences:prefs];
1949         [prefs release];
1950     }
1951 }
1952
1953 - (NSString *)preferencesIdentifier
1954 {
1955     return [[self preferences] identifier];
1956 }
1957
1958
1959 - (void)setUIDelegate:delegate
1960 {
1961     _private->UIDelegate = delegate;
1962     [_private->UIDelegateForwarder release];
1963     _private->UIDelegateForwarder = nil;
1964 }
1965
1966 - UIDelegate
1967 {
1968     return _private->UIDelegate;
1969 }
1970
1971 - (void)setResourceLoadDelegate: delegate
1972 {
1973     _private->resourceProgressDelegate = delegate;
1974     [_private->resourceProgressDelegateForwarder release];
1975     _private->resourceProgressDelegateForwarder = nil;
1976     [self _cacheResourceLoadDelegateImplementations];
1977 }
1978
1979
1980 - resourceLoadDelegate
1981 {
1982     return _private->resourceProgressDelegate;
1983 }
1984
1985
1986 - (void)setDownloadDelegate: delegate
1987 {
1988     _private->downloadDelegate = delegate;
1989 }
1990
1991
1992 - downloadDelegate
1993 {
1994     return _private->downloadDelegate;
1995 }
1996
1997 - (void)setPolicyDelegate:delegate
1998 {
1999     _private->policyDelegate = delegate;
2000     [_private->policyDelegateForwarder release];
2001     _private->policyDelegateForwarder = nil;
2002 }
2003
2004 - policyDelegate
2005 {
2006     return _private->policyDelegate;
2007 }
2008
2009 - (void)setFrameLoadDelegate:delegate
2010 {
2011     _private->frameLoadDelegate = delegate;
2012     [_private->frameLoadDelegateForwarder release];
2013     _private->frameLoadDelegateForwarder = nil;
2014 }
2015
2016 - frameLoadDelegate
2017 {
2018     return _private->frameLoadDelegate;
2019 }
2020
2021 - (WebFrame *)mainFrame
2022 {
2023     // This can be called in initialization, before _private has been set up (3465613)
2024     if (!_private)
2025         return nil;
2026     return [(WebFrameBridge *)[_private->_pageBridge mainFrame] webFrame];
2027 }
2028
2029 - (WebFrame *)selectedFrame
2030 {
2031     // If the first responder is a view in our tree, we get the frame containing the first responder.
2032     // This is faster than searching the frame hierarchy, and will give us a result even in the case
2033     // where the focused frame doesn't actually contain a selection.
2034     WebFrame *focusedFrame = [self _focusedFrame];
2035     if (focusedFrame)
2036         return focusedFrame;
2037     
2038     // If the first responder is outside of our view tree, we search for a frame containing a selection.
2039     // There should be at most only one of these.
2040     return [[self mainFrame] _findFrameWithSelection];
2041     
2042     return nil;
2043 }
2044
2045 - (WebBackForwardList *)backForwardList
2046 {
2047     if (_private->useBackForwardList)
2048         return _private->backForwardList;
2049     return nil;
2050 }
2051
2052 - (void)setMaintainsBackForwardList: (BOOL)flag
2053 {
2054     _private->useBackForwardList = flag;
2055 }
2056
2057 - (BOOL)goBack
2058 {
2059     WebHistoryItem *item = [[self backForwardList] backItem];
2060     
2061     if (item){
2062         [self _goToItem: item withLoadType: WebFrameLoadTypeBack];
2063         return YES;
2064     }
2065     return NO;
2066 }
2067
2068 - (BOOL)goForward
2069 {
2070     WebHistoryItem *item = [[self backForwardList] forwardItem];
2071     
2072     if (item){
2073         [self _goToItem: item withLoadType: WebFrameLoadTypeForward];
2074         return YES;
2075     }
2076     return NO;
2077 }
2078
2079 - (BOOL)goToBackForwardItem:(WebHistoryItem *)item
2080 {
2081     [self _goToItem: item withLoadType: WebFrameLoadTypeIndexedBackForward];
2082     return YES;
2083 }
2084
2085 - (void)setTextSizeMultiplier:(float)m
2086 {
2087     if (_private->textSizeMultiplier == m) {
2088         return;
2089     }
2090     _private->textSizeMultiplier = m;
2091 }
2092
2093 - (float)textSizeMultiplier
2094 {
2095     return _private->textSizeMultiplier;
2096 }
2097
2098 - (void)setApplicationNameForUserAgent:(NSString *)applicationName
2099 {
2100     NSString *name = [applicationName copy];
2101     [_private->applicationNameForUserAgent release];
2102     _private->applicationNameForUserAgent = name;
2103     if (!_private->userAgentOverridden) {
2104         [_private->userAgent release];
2105         _private->userAgent = nil;
2106     }
2107 }
2108
2109 - (NSString *)applicationNameForUserAgent
2110 {
2111     return [[_private->applicationNameForUserAgent retain] autorelease];
2112 }
2113
2114 - (void)setCustomUserAgent:(NSString *)userAgentString
2115 {
2116     NSString *override = [userAgentString copy];
2117     [_private->userAgent release];
2118     _private->userAgent = override;
2119     _private->userAgentOverridden = override != nil;
2120 }
2121
2122 - (NSString *)customUserAgent
2123 {
2124     return _private->userAgentOverridden ? [[_private->userAgent retain] autorelease] : nil;
2125 }
2126
2127 - (void)setMediaStyle:(NSString *)mediaStyle
2128 {
2129     if (_private->mediaStyle != mediaStyle) {
2130         [_private->mediaStyle release];
2131         _private->mediaStyle = [mediaStyle copy];
2132     }
2133 }
2134
2135 - (NSString *)mediaStyle
2136 {
2137     return _private->mediaStyle;
2138 }
2139
2140 - (BOOL)supportsTextEncoding
2141 {
2142     id documentView = [[[self mainFrame] frameView] documentView];
2143     return [documentView conformsToProtocol:@protocol(WebDocumentText)]
2144         && [documentView supportsTextEncoding];
2145 }
2146
2147 - (void)setCustomTextEncodingName:(NSString *)encoding
2148 {
2149     NSString *oldEncoding = [self customTextEncodingName];
2150     if (encoding == oldEncoding || [encoding isEqualToString:oldEncoding]) {
2151         return;
2152     }
2153     [[[self mainFrame] _frameLoader] _reloadAllowingStaleDataWithOverrideEncoding:encoding];
2154 }
2155
2156 - (NSString *)_mainFrameOverrideEncoding
2157 {
2158     WebDataSource *dataSource = [[self mainFrame] provisionalDataSource];
2159     if (dataSource == nil) {
2160         dataSource = [[self mainFrame] dataSource];
2161     }
2162     if (dataSource == nil) {
2163         return nil;
2164     }
2165     return [dataSource _overrideEncoding];
2166 }
2167
2168 - (NSString *)customTextEncodingName
2169 {
2170     return [self _mainFrameOverrideEncoding];
2171 }
2172
2173 - (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script
2174 {
2175     return [[[self mainFrame] _bridge] stringByEvaluatingJavaScriptFromString:script];
2176 }
2177
2178 - (WebScriptObject *)windowScriptObject
2179 {
2180     return [[[self mainFrame] _bridge] windowScriptObject];
2181 }
2182
2183 // Get the appropriate user-agent string for a particular URL.
2184 // Since we no longer automatically spoof, this no longer requires looking at the URL.
2185 - (NSString *)userAgentForURL:(NSURL *)URL
2186 {
2187     NSString *userAgent = _private->userAgent;
2188     if (userAgent) {
2189         return [[userAgent retain] autorelease];
2190     }
2191     
2192     NSString *language = [NSUserDefaults _webkit_preferredLanguageCode];
2193     id sourceVersion = [[NSBundle bundleForClass:[WebView class]]
2194         objectForInfoDictionaryKey:(id)kCFBundleVersionKey];
2195     NSString *applicationName = _private->applicationNameForUserAgent;
2196
2197     if ([applicationName length]) {
2198         userAgent = [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; U; " PROCESSOR " Mac OS X; %@) AppleWebKit/%@ (KHTML, like Gecko) %@",
2199             language, sourceVersion, applicationName];
2200     } else {
2201         userAgent = [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; U; " PROCESSOR " Mac OS X; %@) AppleWebKit/%@ (KHTML, like Gecko)",
2202             language, sourceVersion];
2203     }
2204
2205     _private->userAgent = [userAgent retain];
2206     return userAgent;
2207 }
2208
2209 - (void)setHostWindow:(NSWindow *)hostWindow
2210 {
2211     if (!_private->closed && hostWindow != _private->hostWindow) {
2212         [[self mainFrame] _viewWillMoveToHostWindow:hostWindow];
2213         if (_private->hostWindow)
2214             [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowWillCloseNotification object:_private->hostWindow];
2215         if (hostWindow)
2216             [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillClose:) name:NSWindowWillCloseNotification object:hostWindow];
2217         [_private->hostWindow release];
2218         _private->hostWindow = [hostWindow retain];
2219         [[self mainFrame] _viewDidMoveToHostWindow];
2220     }
2221 }
2222
2223 - (NSWindow *)hostWindow
2224 {
2225     return _private->hostWindow;
2226 }
2227
2228 - (NSView <WebDocumentView> *)documentViewAtWindowPoint:(NSPoint)point
2229 {
2230     return [[self _frameViewAtWindowPoint:point] documentView];
2231 }
2232
2233 - (NSView <WebDocumentDragging> *)_draggingDocumentViewAtWindowPoint:(NSPoint)point
2234 {
2235     NSView <WebDocumentView> *documentView = [self documentViewAtWindowPoint:point];
2236     if ([documentView conformsToProtocol:@protocol(WebDocumentDragging)]) {
2237         return (NSView <WebDocumentDragging> *)documentView;
2238     }
2239     return nil;
2240 }
2241
2242 - (NSDictionary *)_elementAtWindowPoint:(NSPoint)windowPoint
2243 {
2244     WebFrameView *frameView = [self _frameViewAtWindowPoint:windowPoint];
2245     if (!frameView)
2246         return nil;
2247     NSView <WebDocumentView> *documentView = [frameView documentView];
2248     if ([documentView conformsToProtocol:@protocol(WebDocumentElement)]) {
2249         NSPoint point = [documentView convertPoint:windowPoint fromView:nil];
2250         return [(NSView <WebDocumentElement> *)documentView elementAtPoint:point];
2251     }
2252     return [NSDictionary dictionaryWithObject:[frameView webFrame] forKey:WebElementFrameKey];
2253 }
2254
2255 - (NSDictionary *)elementAtPoint:(NSPoint)point
2256 {
2257     return [self _elementAtWindowPoint:[self convertPoint:point toView:nil]];
2258 }
2259
2260 - (void)_setDraggingDocumentView:(NSView <WebDocumentDragging> *)newDraggingView
2261 {
2262     if (_private->draggingDocumentView != newDraggingView) {
2263         [_private->draggingDocumentView release];
2264         _private->draggingDocumentView = [newDraggingView retain];
2265     }
2266 }
2267
2268 - (NSDragOperation)_loadingDragOperationForDraggingInfo:(id <NSDraggingInfo>)draggingInfo
2269 {
2270     if (_private->dragDestinationActionMask & WebDragDestinationActionLoad) {
2271         NSPoint windowPoint = [draggingInfo draggingLocation];
2272         NSView *view = [self hitTest:[[self superview] convertPoint:windowPoint toView:nil]];
2273         // Don't accept the drag over a plug-in since plug-ins may want to handle it.
2274         if (![view isKindOfClass:[WebBaseNetscapePluginView class]] && !_private->editable && !_private->initiatedDrag) {
2275             // If not editing or dragging, use _web_dragOperationForDraggingInfo to find a URL to load on the pasteboard.
2276             return [self _web_dragOperationForDraggingInfo:draggingInfo];
2277         }
2278     }
2279     return NSDragOperationNone;
2280 }
2281
2282 - (NSDragOperation)_delegateDragOperationForDraggingInfo:(id <NSDraggingInfo>)draggingInfo
2283 {
2284     NSPoint windowPoint = [draggingInfo draggingLocation];
2285     NSView <WebDocumentDragging> *newDraggingView = [self _draggingDocumentViewAtWindowPoint:windowPoint];
2286     if (_private->draggingDocumentView != newDraggingView) {
2287         [_private->draggingDocumentView draggingCancelledWithDraggingInfo:draggingInfo];
2288         [self _setDraggingDocumentView:newDraggingView];
2289     }
2290     
2291     _private->dragDestinationActionMask = [[self _UIDelegateForwarder] webView:self dragDestinationActionMaskForDraggingInfo:draggingInfo];
2292     NSDragOperation operation = NSDragOperationNone;
2293     
2294     if (_private->dragDestinationActionMask == WebDragDestinationActionNone) {
2295         [_private->draggingDocumentView draggingCancelledWithDraggingInfo:draggingInfo];
2296     } else {
2297         operation = [_private->draggingDocumentView draggingUpdatedWithDraggingInfo:draggingInfo actionMask:_private->dragDestinationActionMask];
2298         if (operation == NSDragOperationNone) {
2299             return [self _loadingDragOperationForDraggingInfo:draggingInfo];
2300         }
2301     }
2302     
2303     return operation;
2304 }
2305
2306 // The following 2 internal NSView methods are called on the drag destination by make scrolling while dragging work.
2307 // Scrolling while dragging will only work if the drag destination is in a scroll view. The WebView is the drag destination. 
2308 // When dragging to a WebView, the document subview should scroll, but it doesn't because it is not the drag destination. 
2309 // Forward these calls to the document subview to make its scroll view scroll.
2310 - (void)_autoscrollForDraggingInfo:(id)draggingInfo timeDelta:(NSTimeInterval)repeatDelta
2311 {
2312     NSView <WebDocumentView> *documentView = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
2313     [documentView _autoscrollForDraggingInfo:draggingInfo timeDelta:repeatDelta];
2314 }
2315
2316 - (BOOL)_shouldAutoscrollForDraggingInfo:(id)draggingInfo
2317 {
2318     NSView <WebDocumentView> *documentView = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
2319     return [documentView _shouldAutoscrollForDraggingInfo:draggingInfo];
2320 }
2321
2322 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)draggingInfo
2323 {
2324     return [self _delegateDragOperationForDraggingInfo:draggingInfo];
2325 }
2326
2327 - (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)draggingInfo
2328 {
2329     return [self _delegateDragOperationForDraggingInfo:draggingInfo];
2330 }
2331
2332 - (void)draggingExited:(id <NSDraggingInfo>)draggingInfo
2333 {
2334     [_private->draggingDocumentView draggingCancelledWithDraggingInfo:draggingInfo];
2335     [self _setDraggingDocumentView:nil];
2336 }
2337
2338 - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)draggingInfo
2339 {
2340     return YES;
2341 }
2342
2343 - (BOOL)performDragOperation:(id <NSDraggingInfo>)draggingInfo
2344 {
2345     ASSERT(_private->draggingDocumentView == [self _draggingDocumentViewAtWindowPoint:[draggingInfo draggingLocation]]);
2346     
2347     if ([_private->draggingDocumentView concludeDragForDraggingInfo:draggingInfo actionMask:_private->dragDestinationActionMask]) {
2348         [self _setDraggingDocumentView:nil];
2349         return YES;
2350     }
2351     
2352     [self _setDraggingDocumentView:nil];
2353         
2354     if ([self _loadingDragOperationForDraggingInfo:draggingInfo] != NSDragOperationNone) {    
2355         NSURL *URL = [[self class] URLFromPasteboard:[draggingInfo draggingPasteboard]];
2356         if (URL != nil) {
2357             [[self _UIDelegateForwarder] webView:self willPerformDragDestinationAction:WebDragDestinationActionLoad forDraggingInfo:draggingInfo];
2358             NSURLRequest *request = [[NSURLRequest alloc] initWithURL:URL];
2359             [[self mainFrame] loadRequest:request];
2360             [request release];
2361             return YES;
2362         }
2363     }
2364     
2365     return NO;
2366 }
2367
2368 - (NSView *)_hitTest:(NSPoint *)aPoint dragTypes:(NSSet *)types
2369 {
2370     NSView *hitView = [super _hitTest:aPoint dragTypes:types];
2371     if (!hitView && [[self superview] mouse:*aPoint inRect:[self frame]]) {
2372         return self;
2373     } else {
2374         return hitView;
2375     }
2376 }
2377
2378 - (BOOL)acceptsFirstResponder
2379 {
2380     return [[[self mainFrame] frameView] acceptsFirstResponder];
2381 }
2382
2383 - (BOOL)becomeFirstResponder
2384 {
2385     // This works together with setNextKeyView to splice the WebView into
2386     // the key loop similar to the way NSScrollView does this. Note that
2387     // WebFrameView has very similar code.
2388     NSWindow *window = [self window];
2389     WebFrameView *mainFrameView = [[self mainFrame] frameView];
2390     
2391     if ([window keyViewSelectionDirection] == NSSelectingPrevious) {
2392         NSView *previousValidKeyView = [self previousValidKeyView];
2393         if ((previousValidKeyView != self) && (previousValidKeyView != mainFrameView)) {
2394             [window makeFirstResponder:previousValidKeyView];
2395             return YES;
2396         } else {
2397             return NO;
2398         }
2399     }
2400     
2401     if ([mainFrameView acceptsFirstResponder]) {
2402         [window makeFirstResponder:mainFrameView];
2403         return YES;
2404     } 
2405     
2406     return NO;
2407 }
2408
2409 - (NSView *)_webcore_effectiveFirstResponder
2410 {
2411     WebFrameView *frameView = [[self mainFrame] frameView];
2412     return frameView ? [frameView _webcore_effectiveFirstResponder] : [super _webcore_effectiveFirstResponder];
2413 }
2414
2415 - (void)setNextKeyView:(NSView *)aView
2416 {
2417     // This works together with becomeFirstResponder to splice the WebView into
2418     // the key loop similar to the way NSScrollView does this. Note that
2419     // WebFrameView has very similar code.
2420     WebFrameView *mainFrameView = [[self mainFrame] frameView];
2421     if (mainFrameView != nil) {
2422         [mainFrameView setNextKeyView:aView];
2423     } else {
2424         [super setNextKeyView:aView];
2425     }
2426 }
2427
2428 static WebFrame *incrementFrame(WebFrame *curr, BOOL forward, BOOL wrapFlag)
2429 {
2430     return forward ? [curr _nextFrameWithWrap:wrapFlag]
2431                    : [curr _previousFrameWithWrap:wrapFlag];
2432 }
2433
2434 - (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag
2435 {
2436     if (_private->closed)
2437         return NO;
2438
2439     // Get the frame holding the selection, or start with the main frame
2440     WebFrame *startFrame = [self _selectedOrMainFrame];
2441
2442     // Search the first frame, then all the other frames, in order
2443     NSView <WebDocumentSearching> *startSearchView = nil;
2444     BOOL startHasSelection = NO;
2445     WebFrame *frame = startFrame;
2446     do {
2447         id <WebDocumentView> view = [[frame frameView] documentView];
2448         if ([view conformsToProtocol:@protocol(WebDocumentSearching)]) {
2449             NSView <WebDocumentSearching> *searchView = (NSView <WebDocumentSearching> *)view;
2450
2451             // first time through
2452             if (frame == startFrame) {
2453                 // Remember if start even has a selection, to know if we need to search more later
2454                 if ([searchView isKindOfClass:[WebHTMLView class]]) {
2455                     // optimization for the common case, to avoid making giant string for selection
2456                     startHasSelection = [[startFrame _bridge] selectedDOMRange] != nil;
2457                 } else if ([searchView conformsToProtocol:@protocol(WebDocumentText)]) {
2458                     startHasSelection = [(id <WebDocumentText>)searchView selectedString] != nil;
2459                 }
2460                 startSearchView = searchView;
2461             }
2462             
2463             if ([searchView searchFor:string direction:forward caseSensitive:caseFlag wrap:NO]) {
2464                 if (frame != startFrame)
2465                     [startFrame _clearSelection];
2466                 [[self window] makeFirstResponder:searchView];
2467                 return YES;
2468             }
2469         }
2470         frame = incrementFrame(frame, forward, wrapFlag);
2471     } while (frame != nil && frame != startFrame);
2472
2473     // Search contents of startFrame, on the other side of the selection that we did earlier.
2474     // We cheat a bit and just research with wrap on
2475     if (wrapFlag && startHasSelection && startSearchView) {
2476         if ([startSearchView searchFor:string direction:forward caseSensitive:caseFlag wrap:YES]) {
2477             [[self window] makeFirstResponder:startSearchView];
2478             return YES;
2479         }
2480     }
2481     return NO;
2482 }
2483
2484 + (void)registerViewClass:(Class)viewClass representationClass:(Class)representationClass forMIMEType:(NSString *)MIMEType
2485 {
2486     [[WebFrameView _viewTypesAllowImageTypeOmission:YES] setObject:viewClass forKey:MIMEType];
2487     [[WebDataSource _repTypesAllowImageTypeOmission:YES] setObject:representationClass forKey:MIMEType];
2488 }
2489
2490 - (void)setGroupName:(NSString *)groupName
2491 {
2492     [[self _pageBridge] setGroupName:groupName];
2493 }
2494
2495 - (NSString *)groupName
2496 {
2497     return [[self _pageBridge] groupName];
2498 }
2499
2500 - (double)estimatedProgress
2501 {
2502     return _private->progressValue;
2503 }
2504
2505 - (NSArray *)pasteboardTypesForSelection
2506 {
2507     NSView <WebDocumentView> *documentView = [[[self _selectedOrMainFrame] frameView] documentView];
2508     if ([documentView conformsToProtocol:@protocol(WebDocumentSelection)]) {
2509         return [(NSView <WebDocumentSelection> *)documentView pasteboardTypesForSelection];
2510     }
2511     return [NSArray array];
2512 }
2513
2514 - (void)writeSelectionWithPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
2515 {
2516     WebFrameBridge *bridge = [self _bridgeForSelectedOrMainFrame];
2517     if (bridge && [bridge selectionState] != WebSelectionStateRange) {
2518         NSView <WebDocumentView> *documentView = [[[bridge webFrame] frameView] documentView];
2519         if ([documentView conformsToProtocol:@protocol(WebDocumentSelection)]) {
2520             [(NSView <WebDocumentSelection> *)documentView writeSelectionWithPasteboardTypes:types toPasteboard:pasteboard];
2521         }
2522     }
2523 }
2524
2525 - (NSArray *)pasteboardTypesForElement:(NSDictionary *)element
2526 {
2527     if ([element objectForKey:WebElementImageURLKey] != nil) {
2528         return [NSPasteboard _web_writableTypesForImageIncludingArchive:([element objectForKey:WebElementDOMNodeKey] != nil)];
2529     } else if ([element objectForKey:WebElementLinkURLKey] != nil) {
2530         return [NSPasteboard _web_writableTypesForURL];
2531     } else if ([[element objectForKey:WebElementIsSelectedKey] boolValue]) {
2532         return [self pasteboardTypesForSelection];
2533     }
2534     return [NSArray array];
2535 }
2536
2537 - (void)writeElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
2538 {
2539     if ([element objectForKey:WebElementImageURLKey] != nil) {
2540         [self _writeImageForElement:element withPasteboardTypes:types toPasteboard:pasteboard];
2541     } else if ([element objectForKey:WebElementLinkURLKey] != nil) {
2542         [self _writeLinkElement:element withPasteboardTypes:types toPasteboard:pasteboard];
2543     } else if ([[element objectForKey:WebElementIsSelectedKey] boolValue]) {
2544         [self writeSelectionWithPasteboardTypes:types toPasteboard:pasteboard];
2545     }
2546 }
2547
2548 - (void)moveDragCaretToPoint:(NSPoint)point
2549 {
2550     [[[self mainFrame] _bridge] moveDragCaretToPoint:[self convertPoint:point toView:[[[self mainFrame] frameView] documentView]]];
2551 }
2552
2553 - (void)removeDragCaret
2554 {
2555     [[[self mainFrame] _bridge] removeDragCaret];
2556 }
2557
2558 - (void)setMainFrameURL:(NSString *)URLString
2559 {
2560     [[self mainFrame] loadRequest: [NSURLRequest requestWithURL: [NSURL _web_URLWithDataAsString: URLString]]];
2561 }
2562
2563 - (NSString *)mainFrameURL
2564 {
2565     WebDataSource *ds;
2566     ds = [[self mainFrame] provisionalDataSource];
2567     if (!ds)
2568         ds = [[self mainFrame] dataSource];
2569     return [[[ds request] URL] _web_originalDataAsString];
2570 }
2571
2572 - (BOOL)isLoading
2573 {
2574     LOG (Bindings, "isLoading = %d", (int)[self _isLoading]);
2575     return [self _isLoading];
2576 }
2577
2578 - (NSString *)mainFrameTitle
2579 {
2580     NSString *mainFrameTitle = [[[self mainFrame] dataSource] pageTitle];
2581     return (mainFrameTitle != nil) ? mainFrameTitle : (NSString *)@"";
2582 }
2583
2584 - (NSImage *)mainFrameIcon
2585 {
2586     return [[WebIconDatabase sharedIconDatabase] iconForURL:[[[[self mainFrame] dataSource] _URL] _web_originalDataAsString] withSize:WebIconSmallSize];
2587 }
2588
2589 - (DOMDocument *)mainFrameDocument
2590 {
2591     // only return the actual value if the state we're in gives NSTreeController
2592     // enough time to release its observers on the old model
2593     if (_private->mainFrameDocumentReady)
2594         return [[self mainFrame] DOMDocument];
2595     return nil;
2596 }
2597
2598 - (void)setDrawsBackground:(BOOL)drawsBackground
2599 {
2600     if (_private->drawsBackground == drawsBackground)
2601         return;
2602     _private->drawsBackground = drawsBackground;
2603     [[self mainFrame] _updateDrawsBackground];
2604 }
2605
2606 - (BOOL)drawsBackground
2607 {
2608     return _private->drawsBackground;
2609 }
2610
2611 - (void)_inspectElement:(id)sender
2612 {
2613     NSDictionary *element = [sender representedObject];
2614     WebFrame *frame = [element objectForKey:WebElementFrameKey];
2615     DOMNode *node = [element objectForKey:WebElementDOMNodeKey];
2616     if (!node || !frame)
2617         return;
2618
2619     if ([node nodeType] != DOM_ELEMENT_NODE || [node nodeType] != DOM_DOCUMENT_NODE)
2620         node = [node parentNode];
2621
2622     WebInspector *inspector = [WebInspector sharedWebInspector];
2623     [inspector setWebFrame:frame];
2624     [inspector setFocusedDOMNode:node];
2625
2626     node = [node parentNode];
2627     node = [node parentNode];
2628     if (node) // set the root node to something relatively close to the focused node
2629         [inspector setRootDOMNode:node];
2630
2631     [inspector showWindow:nil];
2632 }
2633 @end
2634
2635 @implementation WebView (WebIBActions)
2636
2637 - (IBAction)takeStringURLFrom: sender
2638 {
2639     NSString *URLString = [sender stringValue];
2640     
2641     [[self mainFrame] loadRequest: [NSURLRequest requestWithURL: [NSURL _web_URLWithDataAsString: URLString]]];
2642 }
2643
2644 - (BOOL)canGoBack
2645 {
2646     return [[self backForwardList] backItem] != nil;
2647 }
2648
2649 - (BOOL)canGoForward
2650 {
2651     return [[self backForwardList] forwardItem] != nil;
2652 }
2653
2654 - (IBAction)goBack:(id)sender
2655 {
2656     [self goBack];
2657 }
2658
2659 - (IBAction)goForward:(id)sender
2660 {
2661     [self goForward];
2662 }
2663
2664 - (IBAction)stopLoading:(id)sender
2665 {
2666     [[self mainFrame] stopLoading];
2667 }
2668
2669 - (IBAction)reload:(id)sender
2670 {
2671     [[self mainFrame] reload];
2672 }
2673
2674 #define MinimumTextSizeMultiplier       0.5f
2675 #define MaximumTextSizeMultiplier       3.0f
2676 #define TextSizeMultiplierRatio         1.2f
2677
2678 - (BOOL)canMakeTextSmaller
2679 {
2680     BOOL canShrinkMore = _private->textSizeMultiplier/TextSizeMultiplierRatio > MinimumTextSizeMultiplier;
2681     return [self _performTextSizingSelector:(SEL)0 withObject:nil onTrackingDocs:canShrinkMore selForNonTrackingDocs:@selector(_canMakeTextSmaller) newScaleFactor:0];
2682 }
2683
2684 - (BOOL)canMakeTextLarger
2685 {
2686     BOOL canGrowMore = _private->textSizeMultiplier*TextSizeMultiplierRatio < MaximumTextSizeMultiplier;
2687     return [self _performTextSizingSelector:(SEL)0 withObject:nil onTrackingDocs:canGrowMore selForNonTrackingDocs:@selector(_canMakeTextLarger) newScaleFactor:0];
2688 }
2689
2690 - (IBAction)makeTextSmaller:(id)sender
2691 {
2692     float newScale = _private->textSizeMultiplier / TextSizeMultiplierRatio;
2693     BOOL canShrinkMore = newScale > MinimumTextSizeMultiplier;
2694     [self _performTextSizingSelector:@selector(_makeTextSmaller:) withObject:sender onTrackingDocs:canShrinkMore selForNonTrackingDocs:@selector(_canMakeTextSmaller) newScaleFactor:newScale];
2695 }
2696
2697 - (IBAction)makeTextLarger:(id)sender
2698 {
2699     float newScale = _private->textSizeMultiplier*TextSizeMultiplierRatio;
2700     BOOL canGrowMore = newScale < MaximumTextSizeMultiplier;
2701     [self _performTextSizingSelector:@selector(_makeTextLarger:) withObject:sender onTrackingDocs:canGrowMore selForNonTrackingDocs:@selector(_canMakeTextLarger) newScaleFactor:newScale];
2702 }
2703
2704 - (IBAction)toggleSmartInsertDelete:(id)sender
2705 {
2706     [self setSmartInsertDeleteEnabled:![self smartInsertDeleteEnabled]];
2707 }
2708
2709 - (IBAction)toggleContinuousSpellChecking:(id)sender
2710 {
2711     [self setContinuousSpellCheckingEnabled:![self isContinuousSpellCheckingEnabled]];
2712 }
2713
2714 - (BOOL)_responderValidateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item
2715 {
2716     id responder = [self _responderForResponderOperations];
2717     if (responder != self && [responder respondsToSelector:[item action]]) {
2718         if ([responder respondsToSelector:@selector(validateUserInterfaceItem:)]) {
2719             return [responder validateUserInterfaceItem:item];
2720         }
2721         return YES;
2722     }
2723     return NO;
2724 }
2725
2726 - (BOOL)canMakeTextStandardSize
2727 {
2728     BOOL notAlreadyStandard = _private->textSizeMultiplier != 1.0f;
2729     return [self _performTextSizingSelector:(SEL)0 withObject:nil onTrackingDocs:notAlreadyStandard selForNonTrackingDocs:@selector(_canMakeTextStandardSize) newScaleFactor:0.0f];
2730 }
2731
2732 - (IBAction)makeTextStandardSize:(id)sender
2733 {
2734     BOOL notAlreadyStandard = _private->textSizeMultiplier != 1.0f;
2735     [self _performTextSizingSelector:@selector(_makeTextStandardSize:) withObject:sender onTrackingDocs:notAlreadyStandard selForNonTrackingDocs:@selector(_canMakeTextStandardSize) newScaleFactor:1.0f];
2736 }
2737
2738 #define VALIDATE(name) \
2739     else if (action == @selector(name:)) { return [self _responderValidateUserInterfaceItem:item]; }
2740
2741 - (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item
2742 {
2743     SEL action = [item action];
2744
2745     if (action == @selector(goBack:)) {
2746         return [self canGoBack];
2747     } else if (action == @selector(goForward:)) {
2748         return [self canGoForward];
2749     } else if (action == @selector(makeTextLarger:)) {
2750         return [self canMakeTextLarger];
2751     } else if (action == @selector(makeTextSmaller:)) {
2752         return [self canMakeTextSmaller];
2753     } else if (action == @selector(makeTextStandardSize:)) {
2754         return [self canMakeTextStandardSize];
2755     } else if (action == @selector(reload:)) {
2756         return [[self mainFrame] dataSource] != nil;
2757     } else if (action == @selector(stopLoading:)) {
2758         return [self _isLoading];
2759     } else if (action == @selector(toggleContinuousSpellChecking:)) {
2760         BOOL checkMark = NO;
2761         BOOL retVal = NO;
2762         if ([self _continuousCheckingAllowed]) {
2763             checkMark = [self isContinuousSpellCheckingEnabled];
2764             retVal = YES;
2765         }
2766         if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
2767             NSMenuItem *menuItem = (NSMenuItem *)item;
2768             [menuItem setState:checkMark ? NSOnState : NSOffState];
2769         }
2770         return retVal;
2771     }
2772     FOR_EACH_RESPONDER_SELECTOR(VALIDATE)
2773
2774     return YES;
2775 }
2776
2777 @end
2778
2779 @implementation WebView (WebPendingPublic)
2780
2781 - (void)setMainFrameDocumentReady:(BOOL)mainFrameDocumentReady
2782 {
2783     // by setting this to NO, calls to mainFrameDocument are forced to return nil
2784     // setting this to YES lets it return the actual DOMDocument value
2785     // we use this to tell NSTreeController to reset its observers and clear its state
2786     if (_private->mainFrameDocumentReady == mainFrameDocumentReady)
2787         return;
2788     [self _willChangeValueForKey:_WebMainFrameDocumentKey];
2789     _private->mainFrameDocumentReady = mainFrameDocumentReady;
2790     [self _didChangeValueForKey:_WebMainFrameDocumentKey];
2791     // this will cause observers to call mainFrameDocument where this flag will be checked
2792 }
2793
2794 // This method name is used by Mail on Tiger (but not post-Tiger), so we shouldn't delete it 
2795 // until the day comes when we're no longer supporting Mail on Tiger.
2796 - (WebFrame *)_frameForCurrentSelection
2797 {
2798     return [self _selectedOrMainFrame];
2799 }
2800
2801 - (void)setTabKeyCyclesThroughElements:(BOOL)cyclesElements
2802 {
2803     _private->tabKeyCyclesThroughElementsChanged = YES;
2804     _private->tabKeyCyclesThroughElements = cyclesElements;
2805 }
2806
2807 - (BOOL)tabKeyCyclesThroughElements
2808 {
2809     return _private->tabKeyCyclesThroughElements;
2810 }
2811
2812 - (void)setScriptDebugDelegate:delegate
2813 {
2814     _private->scriptDebugDelegate = delegate;
2815     [_private->scriptDebugDelegateForwarder release];
2816     _private->scriptDebugDelegateForwarder = nil;
2817     if (delegate)
2818         [self _attachScriptDebuggerToAllFrames];
2819     else
2820         [self _detachScriptDebuggerFromAllFrames];
2821 }
2822
2823 - scriptDebugDelegate
2824 {
2825     return _private->scriptDebugDelegate;
2826 }
2827
2828 - (BOOL)shouldClose
2829 {
2830     WebFrameBridge *bridge = [[self mainFrame] _bridge];
2831     if (!bridge)
2832         return YES;
2833     return [bridge shouldClose];
2834 }
2835
2836 - (NSAppleEventDescriptor *)aeDescByEvaluatingJavaScriptFromString:(NSString *)script
2837 {
2838     return [[[self mainFrame] _bridge] aeDescByEvaluatingJavaScriptFromString:script];
2839 }
2840
2841 - (unsigned)markAllMatchesForText:(NSString *)string caseSensitive:(BOOL)caseFlag highlight:(BOOL)highlight
2842 {
2843     WebFrame *frame = [self mainFrame];
2844     unsigned matchCount = 0;
2845     do {
2846         id <WebDocumentView> view = [[frame frameView] documentView];
2847         // FIXME: introduce a protocol, or otherwise make this work with other types
2848         if ([view isKindOfClass:[WebHTMLView class]])
2849             [(WebHTMLView *)view setMarkedTextMatchesAreHighlighted:highlight];
2850             matchCount += [(WebHTMLView *)view markAllMatchesForText:string caseSensitive:caseFlag];
2851
2852         frame = incrementFrame(frame, YES, NO);
2853     } while (frame);
2854     
2855     return matchCount;
2856 }
2857
2858 - (void)unmarkAllTextMatches
2859 {
2860     WebFrame *frame = [self mainFrame];
2861     do {
2862         id <WebDocumentView> view = [[frame frameView] documentView];
2863         // FIXME: introduce a protocol, or otherwise make this work with other types
2864         if ([view isKindOfClass:[WebHTMLView class]])
2865             [(WebHTMLView *)view unmarkAllTextMatches];
2866         
2867         frame = incrementFrame(frame, YES, NO);
2868     } while (frame);
2869 }
2870
2871 - (NSArray *)rectsForTextMatches
2872 {
2873     NSMutableArray *result = [NSMutableArray array];
2874     WebFrame *frame = [self mainFrame];
2875     do {
2876         id <WebDocumentView> view = [[frame frameView] documentView];
2877         // FIXME: introduce a protocol, or otherwise make this work with other types
2878         if ([view isKindOfClass:[WebHTMLView class]]) {
2879             WebHTMLView *htmlView = (WebHTMLView *)view;
2880             NSArray *originalRects = [htmlView rectsForTextMatches];
2881             unsigned rectCount = [originalRects count];
2882             unsigned rectIndex;
2883             NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
2884             for (rectIndex = 0; rectIndex < rectCount; ++rectIndex) {
2885                 NSRect r = [[originalRects objectAtIndex:rectIndex] rectValue];
2886                 if (NSIsEmptyRect(r))
2887                     continue;
2888                 
2889                 // Convert rect to our coordinate system
2890                 r = [htmlView convertRect:r toView:self];
2891                 [result addObject:[NSValue valueWithRect:r]];
2892                 if (rectIndex % 10 == 0)
2893                     [pool drain];
2894             }
2895             [pool release];
2896         }
2897         
2898         frame = incrementFrame(frame, YES, NO);
2899     } while (frame);
2900     
2901     return result;
2902 }
2903
2904 @end
2905
2906 @implementation WebView (WebViewPrintingPrivate)
2907
2908 - (float)_headerHeight
2909 {
2910     if ([[self UIDelegate] respondsToSelector:@selector(webViewHeaderHeight:)]) {
2911         return [[self UIDelegate] webViewHeaderHeight:self];
2912     }
2913     
2914 #ifdef DEBUG_HEADER_AND_FOOTER
2915     return 25;
2916 #else
2917     return 0;
2918 #endif
2919 }
2920
2921 - (float)_footerHeight
2922 {
2923     if ([[self UIDelegate] respondsToSelector:@selector(webViewFooterHeight:)]) {
2924         return [[self UIDelegate] webViewFooterHeight:self];
2925     }
2926     
2927 #ifdef DEBUG_HEADER_AND_FOOTER
2928     return 50;
2929 #else
2930     return 0;
2931 #endif
2932 }
2933
2934 - (void)_drawHeaderInRect:(NSRect)rect
2935 {
2936 #ifdef DEBUG_HEADER_AND_FOOTER
2937     NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
2938     [currentContext saveGraphicsState];
2939     [[NSColor yellowColor] set];
2940     NSRectFill(rect);
2941     [currentContext restoreGraphicsState];
2942 #endif
2943     
2944     if ([[self UIDelegate] respondsToSelector:@selector(webView:drawHeaderInRect:)]) {
2945         NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
2946         [currentContext saveGraphicsState];
2947         NSRectClip(rect);
2948         [[self UIDelegate] webView:self drawHeaderInRect:rect]; 
2949         [currentContext restoreGraphicsState];
2950     }
2951 }
2952
2953 - (void)_drawFooterInRect:(NSRect)rect
2954 {
2955 #ifdef DEBUG_HEADER_AND_FOOTER
2956     NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
2957     [currentContext saveGraphicsState];
2958     [[NSColor cyanColor] set];
2959     NSRectFill(rect);
2960     [currentContext restoreGraphicsState];
2961 #endif
2962     
2963     if ([[self UIDelegate] respondsToSelector:@selector(webView:drawFooterInRect:)]) {
2964         NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
2965         [currentContext saveGraphicsState];
2966         NSRectClip(rect);
2967         [[self UIDelegate] webView:self drawFooterInRect:rect];
2968         [currentContext restoreGraphicsState];
2969     }
2970 }
2971
2972 - (void)_adjustPrintingMarginsForHeaderAndFooter
2973 {
2974     NSPrintOperation *op = [NSPrintOperation currentOperation];
2975     NSPrintInfo *info = [op printInfo];
2976     float scale = [op _web_pageSetupScaleFactor];
2977     [info setTopMargin:[info topMargin] + [self _headerHeight]*scale];
2978     [info setBottomMargin:[info bottomMargin] + [self _footerHeight]*scale];
2979 }
2980
2981 - (void)_drawHeaderAndFooter
2982 {
2983     // The header and footer rect height scales with the page, but the width is always
2984     // all the way across the printed page (inset by printing margins).
2985     NSPrintOperation *op = [NSPrintOperation currentOperation];
2986     float scale = [op _web_pageSetupScaleFactor];
2987     NSPrintInfo *printInfo = [op printInfo];
2988     NSSize paperSize = [printInfo paperSize];
2989     float headerFooterLeft = [printInfo leftMargin]/scale;
2990     float headerFooterWidth = (paperSize.width - ([printInfo leftMargin] + [printInfo rightMargin]))/scale;
2991     NSRect footerRect = NSMakeRect(headerFooterLeft, [printInfo bottomMargin]/scale - [self _footerHeight] , 
2992                                    headerFooterWidth, [self _footerHeight]);
2993     NSRect headerRect = NSMakeRect(headerFooterLeft, (paperSize.height - [printInfo topMargin])/scale, 
2994                                    headerFooterWidth, [self _headerHeight]);
2995     
2996     [self _drawHeaderInRect:headerRect];
2997     [self _drawFooterInRect:footerRect];
2998 }
2999 @end
3000
3001 @implementation WebView (WebDebugBinding)
3002
3003 - (void)addObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context
3004 {
3005     LOG (Bindings, "addObserver:%p forKeyPath:%@ options:%x context:%p", anObserver, keyPath, options, context);
3006     [super addObserver:anObserver forKeyPath:keyPath options:options context:context];
3007 }
3008
3009 - (void)removeObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath
3010 {
3011     LOG (Bindings, "removeObserver:%p forKeyPath:%@", anObserver, keyPath);
3012     [super removeObserver:anObserver forKeyPath:keyPath];
3013 }
3014
3015 @end
3016
3017 //==========================================================================================
3018 // Editing
3019
3020 @implementation WebView (WebViewCSS)
3021
3022 - (DOMCSSStyleDeclaration *)computedStyleForElement:(DOMElement *)element pseudoElement:(NSString *)pseudoElement
3023 {
3024     // FIXME: is this the best level for this conversion?
3025     if (pseudoElement == nil) {
3026         pseudoElement = @"";
3027     }
3028     return [[element ownerDocument] getComputedStyle:element :pseudoElement];
3029 }
3030
3031 @end
3032
3033 @implementation WebView (WebViewEditing)
3034
3035 - (DOMRange *)editableDOMRangeForPoint:(NSPoint)point
3036 {
3037     WebFrameBridge *bridge = [self _bridgeAtPoint:point];
3038     return [bridge editableDOMRangeForPoint:[self convertPoint:point toView:[[[bridge webFrame] frameView] documentView]]];
3039 }
3040
3041 - (BOOL)_shouldChangeSelectedDOMRange:(DOMRange *)currentRange toDOMRange:(DOMRange *)proposedRange affinity:(NSSelectionAffinity)selectionAffinity stillSelecting:(BOOL)flag;
3042 {
3043     return [[self _editingDelegateForwarder] webView:self shouldChangeSelectedDOMRange:currentRange toDOMRange:proposedRange affinity:selectionAffinity stillSelecting:flag];
3044 }
3045
3046 - (BOOL)_shouldBeginEditingInDOMRange:(DOMRange *)range
3047 {
3048     return [[self _editingDelegateForwarder] webView:self shouldBeginEditingInDOMRange:range];
3049 }
3050
3051 - (BOOL)_shouldEndEditingInDOMRange:(DOMRange *)range
3052 {
3053     return [[self _editingDelegateForwarder] webView:self shouldEndEditingInDOMRange:range];
3054 }
3055
3056 - (BOOL)_canPaste
3057 {
3058     id documentView = [[[self mainFrame] frameView] documentView];
3059     return [documentView respondsToSelector:@selector(_canPaste)] && [documentView _canPaste];
3060 }
3061
3062 - (BOOL)maintainsInactiveSelection
3063 {
3064     return NO;
3065 }
3066
3067 - (void)setSelectedDOMRange:(DOMRange *)range affinity:(NSSelectionAffinity)selectionAffinity
3068 {
3069     if (range == nil) {
3070         [[self _bridgeForSelectedOrMainFrame] deselectText];
3071     } else {
3072         // Derive the bridge to use from the range passed in.
3073         // Using _bridgeForSelectedOrMainFrame could give us a different document than
3074         // the one the range uses.
3075         [[[range startContainer] _bridge] setSelectedDOMRange:range affinity:selectionAffinity closeTyping:YES];
3076     }
3077 }
3078
3079 - (DOMRange *)selectedDOMRange
3080 {
3081     return [[self _bridgeForSelectedOrMainFrame] selectedDOMRange];
3082 }
3083
3084 - (NSSelectionAffinity)selectionAffinity
3085 {
3086     return [[self _bridgeForSelectedOrMainFrame] selectionAffinity];
3087 }
3088
3089 - (void)setEditable:(BOOL)flag
3090 {
3091     if (_private->editable != flag) {
3092         _private->editable = flag;
3093         if (!_private->tabKeyCyclesThroughElementsChanged)
3094             _private->tabKeyCyclesThroughElements = !flag;
3095         WebFrameBridge *bridge = [[self mainFrame] _bridge];
3096         if (flag) {
3097             [bridge applyEditingStyleToBodyElement];
3098             // If the WebView is made editable and the selection is empty, set it to something.
3099             if (![self selectedDOMRange])
3100                 [bridge setSelectionFromNone];
3101         } else
3102             [bridge removeEditingStyleFromBodyElement];
3103     }
3104 }
3105
3106 - (BOOL)isEditable
3107 {
3108     return _private->editable;
3109 }
3110
3111 - (void)setTypingStyle:(DOMCSSStyleDeclaration *)style
3112 {
3113     // We don't know enough at thls level to pass in a relevant WebUndoAction; we'd have to
3114     // change the API to allow this.
3115     [[self _bridgeForSelectedOrMainFrame] setTypingStyle:style withUndoAction:WebUndoActionUnspecified];
3116 }
3117
3118 - (DOMCSSStyleDeclaration *)typingStyle
3119 {
3120     return [[self _bridgeForSelectedOrMainFrame] typingStyle];
3121 }
3122
3123 - (void)setSmartInsertDeleteEnabled:(BOOL)flag
3124 {
3125     _private->smartInsertDeleteEnabled = flag;
3126 }
3127
3128 - (BOOL)smartInsertDeleteEnabled
3129 {
3130     return _private->smartInsertDeleteEnabled;
3131 }
3132
3133 - (void)setContinuousSpellCheckingEnabled:(BOOL)flag
3134 {
3135     _private->continuousSpellCheckingEnabled = flag;
3136     if ([self isContinuousSpellCheckingEnabled]) {
3137         [[self class] _preflightSpellChecker];
3138     } else {
3139         [[self mainFrame] _unmarkAllMisspellings];
3140     }
3141 }
3142
3143 - (BOOL)isContinuousSpellCheckingEnabled
3144 {
3145     return _private->continuousSpellCheckingEnabled && [self _continuousCheckingAllowed];
3146 }
3147
3148 - (WebNSInteger)spellCheckerDocumentTag
3149 {
3150     if (!_private->hasSpellCheckerDocumentTag) {
3151         _private->spellCheckerDocumentTag = [NSSpellChecker uniqueSpellDocumentTag];
3152         _private->hasSpellCheckerDocumentTag = YES;
3153     }
3154     return _private->spellCheckerDocumentTag;
3155 }
3156
3157 - (NSUndoManager *)undoManager
3158 {
3159     NSUndoManager *undoManager = [[self _editingDelegateForwarder] undoManagerForWebView:self];
3160     if (undoManager) {
3161         return undoManager;
3162     }
3163     return [super undoManager];
3164 }
3165
3166 - (void)registerForEditingDelegateNotification:(NSString *)name selector:(SEL)selector
3167 {
3168     NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
3169     if ([_private->editingDelegate respondsToSelector:selector])
3170         [defaultCenter addObserver:_private->editingDelegate selector:selector name:name object:self];
3171 }
3172
3173 - (void)setEditingDelegate:(id)delegate
3174 {
3175     if (_private->editingDelegate == delegate)
3176         return;
3177
3178     NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
3179
3180     // remove notifications from current delegate
3181     [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidBeginEditingNotification object:self];
3182     [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidChangeNotification object:self];
3183     [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidEndEditingNotification object:self];
3184     [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidChangeTypingStyleNotification object:self];
3185     [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidChangeSelectionNotification object:self];
3186     
3187     _private->editingDelegate = delegate;
3188     [_private->editingDelegateForwarder release];
3189     _private->editingDelegateForwarder = nil;
3190     
3191     // add notifications for new delegate
3192     [self registerForEditingDelegateNotification:WebViewDidBeginEditingNotification selector:@selector(webViewDidBeginEditing:)];
3193     [self registerForEditingDelegateNotification:WebViewDidChangeNotification selector:@selector(webViewDidChange:)];
3194     [self registerForEditingDelegateNotification:WebViewDidEndEditingNotification selector:@selector(webViewDidEndEditing:)];
3195     [self registerForEditingDelegateNotification:WebViewDidChangeTypingStyleNotification selector:@selector(webViewDidChangeTypingStyle:)];
3196     [self registerForEditingDelegateNotification:WebViewDidChangeSelectionNotification selector:@selector(webViewDidChangeSelection:)];
3197 }
3198
3199 - (id)editingDelegate
3200 {
3201     return _private->editingDelegate;
3202 }
3203
3204 - (DOMCSSStyleDeclaration *)styleDeclarationWithText:(NSString *)text
3205 {
3206     // FIXME: Should this really be attached to the document with the current selection?
3207     DOMCSSStyleDeclaration *decl = [[[self _bridgeForSelectedOrMainFrame] DOMDocument] createCSSStyleDeclaration];
3208     [decl setCssText:text];
3209     return decl;
3210 }
3211
3212 @end
3213
3214 @implementation WebView (WebViewUndoableEditing)
3215
3216 - (void)replaceSelectionWithNode:(DOMNode *)node
3217 {
3218     [[self _bridgeForSelectedOrMainFrame] replaceSelectionWithNode:node selectReplacement:YES smartReplace:NO matchStyle:NO];
3219 }    
3220
3221 - (void)replaceSelectionWithText:(NSString *)text
3222 {
3223     [[self _bridgeForSelectedOrMainFrame] replaceSelectionWithText:text selectReplacement:YES smartReplace:NO];
3224 }
3225
3226 - (void)replaceSelectionWithMarkupString:(NSString *)markupString
3227 {
3228     [[self _bridgeForSelectedOrMainFrame] replaceSelectionWithMarkupString:markupString baseURLString:nil selectReplacement:YES smartReplace:NO];
3229 }
3230
3231 - (void)replaceSelectionWithArchive:(WebArchive *)archive
3232 {
3233     [[[[self _bridgeForSelectedOrMainFrame] webFrame] dataSource] _replaceSelectionWithArchive:archive selectReplacement:YES];
3234 }
3235
3236 - (void)deleteSelection
3237 {
3238     WebFrameBridge *bridge = [self _bridgeForSelectedOrMainFrame];
3239     [bridge deleteSelectionWithSmartDelete:[(WebHTMLView *)[[[bridge webFrame] frameView] documentView] _canSmartCopyOrDelete]];
3240 }
3241     
3242 - (void)applyStyle:(DOMCSSStyleDeclaration *)style
3243 {
3244     // We don't know enough at thls level to pass in a relevant WebUndoAction; we'd have to
3245     // change the API to allow this.
3246     [[self _bridgeForSelectedOrMainFrame] applyStyle:style withUndoAction:WebUndoActionUnspecified];
3247 }
3248
3249 @end
3250
3251 @implementation WebView (WebViewEditingActions)
3252
3253 - (void)_performResponderOperation:(SEL)selector with:(id)parameter
3254 {
3255     static BOOL reentered = NO;
3256     if (reentered) {
3257         [[self nextResponder] tryToPerform:selector with:parameter];
3258         return;
3259     }
3260
3261     // There are two possibilities here.
3262     //
3263     // One is that WebView has been called in its role as part of the responder chain.
3264     // In that case, it's fine to call the first responder and end up calling down the
3265     // responder chain again. Later we will return here with reentered = YES and continue
3266     // past the WebView.
3267     //
3268     // The other is that we are being called directly, in which case we want to pass the
3269     // selector down to the view inside us that can handle it, and continue down the
3270     // responder chain as usual.
3271
3272     // Pass this selector down to the first responder.
3273     NSResponder *responder = [self _responderForResponderOperations];
3274     reentered = YES;
3275     [responder tryToPerform:selector with:parameter];
3276     reentered = NO;
3277 }
3278
3279 #define FORWARD(name) \
3280     - (void)name:(id)sender { [self _performResponderOperation:_cmd with:sender]; }
3281
3282 FOR_EACH_RESPONDER_SELECTOR(FORWARD)
3283
3284 - (void)insertText:(NSString *)text
3285 {
3286     [self _performResponderOperation:_cmd with:text];
3287 }
3288
3289 @end
3290
3291 @implementation WebView (WebViewEditingInMail)
3292
3293 - (void)_insertNewlineInQuotedContent;
3294 {
3295     [[self _bridgeForSelectedOrMainFrame] insertParagraphSeparatorInQuotedContent];
3296 }
3297
3298 - (BOOL)_selectWordBeforeMenuEvent
3299 {
3300     return _private->selectWordBeforeMenuEvent;
3301 }
3302
3303 - (void)_setSelectWordBeforeMenuEvent:(BOOL)flag
3304 {
3305     _private->selectWordBeforeMenuEvent = flag;
3306 }
3307
3308 - (void)_replaceSelectionWithNode:(DOMNode *)node matchStyle:(BOOL)matchStyle
3309 {
3310     [[self _bridgeForSelectedOrMainFrame] replaceSelectionWithNode:node selectReplacement:YES smartReplace:NO matchStyle:matchStyle];
3311 }
3312
3313 @end
3314
3315 static WebFrameView *containingFrameView(NSView *view)
3316 {
3317     while (view && ![view isKindOfClass:[WebFrameView class]])
3318         view = [view superview];
3319     return (WebFrameView *)view;    
3320 }
3321
3322 @implementation WebView (WebFileInternal)
3323
3324 - (WebFrame *)_focusedFrame
3325 {
3326     NSResponder *resp = [[self window] firstResponder];
3327     if (resp && [resp isKindOfClass:[NSView class]] && [(NSView *)resp isDescendantOf:[[self mainFrame] frameView]]) {
3328         WebFrameView *frameView = containingFrameView((NSView *)resp);
3329         ASSERT(frameView != nil);
3330         return [frameView webFrame];
3331     }
3332     
3333     return nil;
3334 }
3335
3336 - (WebFrame *)_selectedOrMainFrame
3337 {
3338     WebFrame *result = [self selectedFrame];
3339     if (result == nil)
3340         result = [self mainFrame];
3341     return result;
3342 }
3343
3344 - (WebFrameBridge *)_bridgeForSelectedOrMainFrame
3345 {
3346     return [[self _selectedOrMainFrame] _bridge];
3347 }
3348
3349 - (BOOL)_isLoading
3350 {
3351     WebFrame *mainFrame = [self mainFrame];
3352     return [[mainFrame dataSource] isLoading]
3353         || [[mainFrame provisionalDataSource] isLoading];
3354 }
3355
3356 - (WebFrameView *)_frameViewAtWindowPoint:(NSPoint)point
3357 {
3358     if (_private->closed)
3359         return nil;
3360     NSView *view = [self hitTest:[[self superview] convertPoint:point fromView:nil]];
3361     if (![view isDescendantOf:[[self mainFrame] frameView]])
3362         return nil;
3363     WebFrameView *frameView = containingFrameView(view);
3364     ASSERT(frameView);
3365     return frameView;
3366 }
3367
3368 - (WebFrameBridge *)_bridgeAtPoint:(NSPoint)point
3369 {
3370     return [[[self _frameViewAtWindowPoint:[self convertPoint:point toView:nil]] webFrame] _bridge];
3371 }
3372
3373 + (void)_preflightSpellCheckerNow:(id)sender
3374 {
3375     [[NSSpellChecker sharedSpellChecker] _preflightChosenSpellServer];
3376 }
3377
3378 + (void)_preflightSpellChecker
3379 {
3380     // As AppKit does, we wish to delay tickling the shared spellchecker into existence on application launch.
3381     if ([NSSpellChecker sharedSpellCheckerExists]) {
3382         [self _preflightSpellCheckerNow:self];
3383     } else {
3384         [self performSelector:@selector(_preflightSpellCheckerNow:) withObject:self afterDelay:2.0];
3385     }
3386 }
3387
3388 - (BOOL)_continuousCheckingAllowed
3389 {
3390     static BOOL allowContinuousSpellChecking = YES;
3391     static BOOL readAllowContinuousSpellCheckingDefault = NO;
3392     if (!readAllowContinuousSpellCheckingDefault) {
3393         if ([[NSUserDefaults standardUserDefaults] objectForKey:@"NSAllowContinuousSpellChecking"]) {
3394             allowContinuousSpellChecking = [[NSUserDefaults standardUserDefaults] boolForKey:@"NSAllowContinuousSpellChecking"];
3395         }
3396         readAllowContinuousSpellCheckingDefault = YES;
3397     }
3398     return allowContinuousSpellChecking;
3399 }
3400
3401 - (NSResponder *)_responderForResponderOperations
3402 {
3403     NSResponder *responder = [[self window] firstResponder];
3404     WebFrameView *mainFrameView = [[self mainFrame] frameView];
3405     
3406     // If the current responder is outside of the webview, use our main frameView or its
3407     // document view. We also do this for subviews of self that are siblings of the main
3408     // frameView since clients might insert non-webview-related views there (see 4552713).
3409     if (responder != self && ![mainFrameView _web_firstResponderIsSelfOrDescendantView]) {
3410         responder = [mainFrameView documentView];
3411         if (!responder)
3412             responder = mainFrameView;
3413     }
3414     return responder;
3415 }
3416
3417 - (void)_searchWithGoogleFromMenu:(id)sender
3418 {
3419     id documentView = [[[self selectedFrame] frameView] documentView];
3420     if (![documentView conformsToProtocol:@protocol(WebDocumentText)]) {
3421         return;
3422     }
3423     
3424     NSString *selectedString = [(id <WebDocumentText>)documentView selectedString];
3425     if ([selectedString length] == 0) {
3426         return;
3427     }
3428     
3429     NSPasteboard *pasteboard = [NSPasteboard pasteboardWithUniqueName];
3430     [pasteboard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
3431     NSMutableString *s = [selectedString mutableCopy];
3432     const unichar nonBreakingSpaceCharacter = 0xA0;
3433     NSString *nonBreakingSpaceString = [NSString stringWithCharacters:&nonBreakingSpaceCharacter length:1];
3434     [s replaceOccurrencesOfString:nonBreakingSpaceString withString:@" " options:0 range:NSMakeRange(0, [s length])];
3435     [pasteboard setString:s forType:NSStringPboardType];
3436     [s release];
3437     
3438     // FIXME: seems fragile to use the service by name, but this is what AppKit does
3439     NSPerformService(@"Search With Google", pasteboard);
3440 }
3441
3442 - (void)_searchWithSpotlightFromMenu:(id)sender
3443 {
3444     id documentView = [[[self selectedFrame] frameView] documentView];
3445     if (![documentView conformsToProtocol:@protocol(WebDocumentText)]) {
3446         return;
3447     }
3448     
3449     NSString *selectedString = [(id <WebDocumentText>)documentView selectedString];
3450     if ([selectedString length] == 0) {
3451         return;
3452     }
3453
3454     (void)HISearchWindowShow((CFStringRef)selectedString, kNilOptions);
3455 }
3456
3457 // Slightly funky method that lets us have one copy of the logic for finding docViews that can do
3458 // text sizing.  It returns whether it found any "suitable" doc views.  It sends sel to any suitable
3459 // doc views, or if sel==0 we do nothing to them.  For doc views that track our size factor, they are
3460 // suitable if doTrackingViews==YES (which in practice means that our size factor isn't at its max or
3461 // min).  For doc views that don't track it, we send them testSel to determine suitablility.  If we
3462 // do find any suitable tracking doc views and newScaleFactor!=0, we will set the common scale factor
3463 // to that new factor before we send sel to any of them. 
3464 - (BOOL)_performTextSizingSelector:(SEL)sel withObject:(id)arg onTrackingDocs:(BOOL)doTrackingViews selForNonTrackingDocs:(SEL)testSel newScaleFactor:(float)newScaleFactor
3465 {
3466     if ([[self mainFrame] dataSource] == nil) {
3467         return NO;
3468     }
3469     
3470     BOOL foundSome = NO;
3471     NSArray *docViews = [[self mainFrame] _documentViews];
3472     int i;
3473     for (i = [docViews count]-1; i >= 0; i--) {
3474         id docView = [docViews objectAtIndex:i];
3475         if ([docView conformsToProtocol:@protocol(_WebDocumentTextSizing)]) {
3476             id <_WebDocumentTextSizing> sizingDocView = (id <_WebDocumentTextSizing>)docView;
3477             BOOL isSuitable;
3478             if ([sizingDocView _tracksCommonSizeFactor]) {
3479                 isSuitable = doTrackingViews;
3480                 if (isSuitable && newScaleFactor != 0) {
3481                     [self setTextSizeMultiplier:newScaleFactor];
3482                 }
3483             } else {
3484                 // Incantation to perform a selector returning a BOOL.
3485                 isSuitable = ((BOOL(*)(id, SEL))objc_msgSend)(sizingDocView, testSel);
3486             }
3487             
3488             if (isSuitable) {
3489                 if (sel != 0) {
3490                     foundSome = YES;
3491                     [sizingDocView performSelector:sel withObject:arg];
3492                 } else {
3493                     // if we're just called for the benefit of the return value, we can return at first match
3494                     return YES;
3495                 }
3496             }
3497         }
3498     }
3499     
3500     return foundSome;
3501 }
3502
3503 @end
3504
3505 @implementation WebView (WebViewBridge)
3506
3507 - (WebPageBridge *)_pageBridge
3508 {
3509     return _private->_pageBridge;
3510 }
3511
3512 @end