3 Copyright 2001, 2002 Apple, Inc. All rights reserved.
6 #import <WebKit/WebViewInternal.h>
9 #import <WebKit/DOMExtensions.h>
10 #import <WebKit/WebAssertions.h>
11 #import <WebKit/WebBackForwardList.h>
12 #import <WebKit/WebBaseNetscapePluginView.h>
13 #import <WebKit/WebBridge.h>
14 #import <WebKit/WebControllerSets.h>
15 #import <WebKit/WebDashboardRegion.h>
16 #import <WebKit/WebDataProtocol.h>
17 #import <WebKit/WebDataSourcePrivate.h>
18 #import <WebKit/WebDefaultEditingDelegate.h>
19 #import <WebKit/WebDefaultFrameLoadDelegate.h>
20 #import <WebKit/WebDefaultPolicyDelegate.h>
21 #import <WebKit/WebDefaultResourceLoadDelegate.h>
22 #import <WebKit/WebDefaultUIDelegate.h>
23 #import <WebKit/WebDOMOperationsPrivate.h>
24 #import <WebKit/WebDocument.h>
25 #import <WebKit/WebDocumentInternal.h>
26 #import <WebKit/WebDynamicScrollBarsView.h>
27 #import <WebKit/WebDownload.h>
28 #import <WebKit/WebEditingDelegate.h>
29 #import <WebKit/WebException.h>
30 #import <WebKit/WebFormDelegatePrivate.h>
31 #import <WebKit/WebFrameInternal.h>
32 #import <WebKit/WebFrameViewInternal.h>
33 #import <WebKit/WebHistoryItemPrivate.h>
34 #import <WebKit/WebHTMLRepresentation.h>
35 #import <WebKit/WebHTMLViewInternal.h>
36 #import <WebKit/WebIconDatabase.h>
37 #import <WebKit/WebKitErrors.h>
38 #import <WebKit/WebKitLogging.h>
39 #import <WebKit/WebKitStatisticsPrivate.h>
40 #import <WebKit/WebNSObjectExtras.h>
41 #import <WebKit/WebNSPasteboardExtras.h>
42 #import <WebKit/WebNSPrintOperationExtras.h>
43 #import <WebKit/WebNSEventExtras.h>
44 #import <WebKit/WebNSURLExtras.h>
45 #import <WebKit/WebNSViewExtras.h>
46 #import <WebKit/WebPluginDatabase.h>
47 #import <WebKit/WebPolicyDelegate.h>
48 #import <WebKit/WebPreferencesPrivate.h>
49 #import <WebKit/WebResourceLoadDelegate.h>
50 #import <WebKit/WebTextView.h>
51 #import <WebKit/WebTextRepresentation.h>
52 #import <WebKit/WebTextRenderer.h>
53 #import <WebKit/WebUIDelegate.h>
54 #import <WebKit/WebUIDelegatePrivate.h>
56 #import <WebCore/WebCoreEncodings.h>
57 #import <WebCore/WebCoreSettings.h>
58 #import <WebCore/WebCoreView.h>
60 #import <Foundation/NSData_NSURLExtras.h>
61 #import <Foundation/NSDictionary_NSURLExtras.h>
62 #import <Foundation/NSString_NSURLExtras.h>
63 #import <Foundation/NSURLConnection.h>
64 #import <Foundation/NSURLDownloadPrivate.h>
65 #import <Foundation/NSURLFileTypeMappings.h>
66 #import <Foundation/NSURLRequestPrivate.h>
67 #import <Foundation/NSUserDefaults_NSURLExtras.h>
69 #if !BUILDING_ON_PANTHER
70 #include <CoreGraphics/CGSConnection.h>
73 #define FOR_EACH_RESPONDER_SELECTOR(macro) \
75 macro(alignJustified) \
78 macro(capitalizeWord) \
79 macro(centerSelectionInVisibleArea) \
80 macro(changeAttributes) \
82 macro(changeDocumentBackgroundColor) \
84 macro(checkSpelling) \
90 macro(deleteBackward) \
91 macro(deleteBackwardByDecomposingPreviousCharacter) \
92 macro(deleteForward) \
93 macro(deleteToBeginningOfLine) \
94 macro(deleteToBeginningOfParagraph) \
95 macro(deleteToEndOfLine) \
96 macro(deleteToEndOfParagraph) \
97 macro(deleteWordBackward) \
98 macro(deleteWordForward) \
99 macro(ignoreSpelling) \
101 macro(insertBacktab) \
102 macro(insertNewline) \
103 macro(insertNewlineIgnoringFieldEditor) \
104 macro(insertParagraphSeparator) \
106 macro(insertTabIgnoringFieldEditor) \
107 macro(lowercaseWord) \
108 macro(moveBackward) \
109 macro(moveBackwardAndModifySelection) \
111 macro(moveDownAndModifySelection) \
113 macro(moveForwardAndModifySelection) \
115 macro(moveLeftAndModifySelection) \
117 macro(moveRightAndModifySelection) \
118 macro(moveToBeginningOfDocument) \
119 macro(moveToBeginningOfDocumentAndModifySelection) \
120 macro(moveToBeginningOfLine) \
121 macro(moveToBeginningOfLineAndModifySelection) \
122 macro(moveToBeginningOfParagraph) \
123 macro(moveToBeginningOfParagraphAndModifySelection) \
124 macro(moveToEndOfDocument) \
125 macro(moveToEndOfDocumentAndModifySelection) \
126 macro(moveToEndOfLine) \
127 macro(moveToEndOfLineAndModifySelection) \
128 macro(moveToEndOfParagraph) \
129 macro(moveToEndOfParagraphAndModifySelection) \
131 macro(moveUpAndModifySelection) \
132 macro(moveWordBackward) \
133 macro(moveWordBackwardAndModifySelection) \
134 macro(moveWordForward) \
135 macro(moveWordForwardAndModifySelection) \
136 macro(moveWordLeft) \
137 macro(moveWordLeftAndModifySelection) \
138 macro(moveWordRight) \
139 macro(moveWordRightAndModifySelection) \
143 macro(pasteAsPlainText) \
144 macro(pasteAsRichText) \
146 macro(performFindPanelAction) \
147 macro(scrollLineDown) \
148 macro(scrollLineUp) \
149 macro(scrollPageDown) \
150 macro(scrollPageUp) \
153 macro(selectParagraph) \
155 macro(showGuessPanel) \
156 macro(startSpeaking) \
157 macro(stopSpeaking) \
162 macro(uppercaseWord) \
164 macro(yankAndSelect) \
166 @interface NSSpellChecker (AppKitSecretsIKnow)
167 - (void)_preflightChosenSpellServer;
170 @interface NSView (AppKitSecretsIKnow)
171 - (NSView *)_hitTest:(NSPoint *)aPoint dragTypes:(NSSet *)types;
172 - (void)_autoscrollForDraggingInfo:(id)dragInfo timeDelta:(NSTimeInterval)repeatDelta;
173 - (BOOL)_shouldAutoscrollForDraggingInfo:(id)dragInfo;
176 #if !BUILDING_ON_PANTHER
177 @interface NSApplication (AppKitSecrectsIKnow)
178 - (CGSConnectionID)contextID;
182 @interface WebView (WebFileInternal)
183 - (void)_preflightSpellChecker;
184 - (BOOL)_continuousCheckingAllowed;
185 - (NSResponder *)_responderForResponderOperations;
188 NSString *WebElementDOMNodeKey = @"WebElementDOMNode";
189 NSString *WebElementFrameKey = @"WebElementFrame";
190 NSString *WebElementImageKey = @"WebElementImage";
191 NSString *WebElementImageAltStringKey = @"WebElementImageAltString";
192 NSString *WebElementImageRectKey = @"WebElementImageRect";
193 NSString *WebElementImageURLKey = @"WebElementImageURL";
194 NSString *WebElementIsSelectedKey = @"WebElementIsSelected";
195 NSString *WebElementLinkURLKey = @"WebElementLinkURL";
196 NSString *WebElementLinkTargetFrameKey = @"WebElementTargetFrame";
197 NSString *WebElementLinkLabelKey = @"WebElementLinkLabel";
198 NSString *WebElementLinkTitleKey = @"WebElementLinkTitle";
200 NSString *WebViewProgressStartedNotification = @"WebProgressStartedNotification";
201 NSString *WebViewProgressEstimateChangedNotification = @"WebProgressEstimateChangedNotification";
202 NSString *WebViewProgressFinishedNotification = @"WebProgressFinishedNotification";
204 NSString * const WebViewDidBeginEditingNotification = @"WebViewDidBeginEditingNotification";
205 NSString * const WebViewDidChangeNotification = @"WebViewDidChangeNotification";
206 NSString * const WebViewDidEndEditingNotification = @"WebViewDidEndEditingNotification";
207 NSString * const WebViewDidChangeTypingStyleNotification = @"WebViewDidChangeTypingStyleNotification";
208 NSString * const WebViewDidChangeSelectionNotification = @"WebViewDidChangeSelectionNotification";
210 enum { WebViewVersion = 2 };
212 #define timedLayoutSize 4096
214 static NSMutableSet *schemesWithRepresentationsSet;
216 NSString *_WebCanGoBackKey = @"canGoBack";
217 NSString *_WebCanGoForwardKey = @"canGoForward";
218 NSString *_WebEstimatedProgressKey = @"estimatedProgress";
219 NSString *_WebIsLoadingKey = @"isLoading";
220 NSString *_WebMainFrameIconKey = @"mainFrameIcon";
221 NSString *_WebMainFrameTitleKey = @"mainFrameTitle";
222 NSString *_WebMainFrameURLKey = @"mainFrameURL";
224 @interface WebProgressItem : NSObject
227 long long bytesReceived;
228 long long estimatedLength;
232 @implementation WebProgressItem
235 static BOOL shouldUseFontSmoothing = YES;
237 @implementation WebViewPrivate
241 backForwardList = [[WebBackForwardList alloc] init];
242 textSizeMultiplier = 1;
243 progressNotificationInterval = 0.02;
244 progressNotificationTimeInterval = 0.1;
245 settings = [[WebCoreSettings alloc] init];
246 dashboardBehaviorAllowWheelScrolling = YES;
253 ASSERT(mainFrame == nil);
254 ASSERT(draggingDocumentView == nil);
255 ASSERT(dragCaretBridge == nil);
257 [backForwardList release];
258 [applicationNameForUserAgent release];
261 [preferences release];
263 [hostWindow release];
265 [policyDelegateForwarder release];
266 [resourceProgressDelegateForwarder release];
267 [UIDelegateForwarder release];
268 [frameLoadDelegateForwarder release];
269 [editingDelegateForwarder release];
271 [progressItems release];
273 [mediaStyle release];
280 @implementation WebView (WebPrivate)
282 #ifdef DEBUG_WIDGET_DRAWING
283 static bool debugWidget = true;
284 - (void)drawRect:(NSRect)rect
286 [[NSColor blueColor] set];
289 NSRect htmlViewRect = [[[[self mainFrame] frameView] documentView] frame];
292 while (debugWidget) {
297 NSLog (@"%s: rect: (%0.f,%0.f) %0.f %0.f, htmlViewRect: (%0.f,%0.f) %0.f %0.f\n",
298 __PRETTY_FUNCTION__, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height,
299 htmlViewRect.origin.x, htmlViewRect.origin.y, htmlViewRect.size.width, htmlViewRect.size.height
302 [super drawRect:rect];
306 + (NSArray *)_supportedMIMETypes
308 // Load the plug-in DB allowing plug-ins to install types.
309 [WebPluginDatabase installedPlugins];
310 return [[WebFrameView _viewTypesAllowImageTypeOmission:NO] allKeys];
313 + (NSArray *)_supportedFileExtensions
315 NSMutableSet *extensions = [[NSMutableSet alloc] init];
316 NSArray *MIMETypes = [self _supportedMIMETypes];
317 NSEnumerator *enumerator = [MIMETypes objectEnumerator];
319 NSURLFileTypeMappings *mappings = [NSURLFileTypeMappings sharedMappings];
320 while ((MIMEType = [enumerator nextObject]) != nil) {
321 NSArray *extensionsForType = [mappings extensionsForMIMEType:MIMEType];
322 if (extensionsForType) {
323 [extensions addObjectsFromArray:extensionsForType];
326 NSArray *uniqueExtensions = [extensions allObjects];
327 [extensions release];
328 return uniqueExtensions;
331 + (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType;
333 MIMEType = [MIMEType lowercaseString];
337 // Simple optimization that avoids loading the plug-in DB and image types for the HTML case.
338 if ([self canShowMIMETypeAsHTML:MIMEType]) {
339 viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:YES] _web_objectForMIMEType:MIMEType];
340 repClass = [[WebDataSource _repTypesAllowImageTypeOmission:YES] _web_objectForMIMEType:MIMEType];
341 if (viewClass && repClass) {
352 // Load the plug-in DB allowing plug-ins to install types.
353 [WebPluginDatabase installedPlugins];
355 // Load the image types and get the view class and rep class. This should be the fullest picture of all handled types.
356 viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:NO] _web_objectForMIMEType:MIMEType];
357 repClass = [[WebDataSource _repTypesAllowImageTypeOmission:NO] _web_objectForMIMEType:MIMEType];
358 if (viewClass && repClass) {
359 // Special-case WebTextView for text types that shouldn't be shown.
360 if (viewClass == [WebTextView class] &&
361 repClass == [WebTextRepresentation class] &&
362 [[WebTextView unsupportedTextMIMETypes] containsObject:MIMEType]) {
377 + (void)_setAlwaysUseATSU:(BOOL)f
379 [WebTextRenderer _setAlwaysUseATSU:f];
382 + (BOOL)canShowFile:(NSString *)path
384 return [[self class] canShowMIMEType:[WebView _MIMETypeForFile:path]];
387 + (NSString *)suggestedFileExtensionForMIMEType:(NSString *)type
389 return [[NSURLFileTypeMappings sharedMappings] preferredExtensionForMIMEType:type];
394 if (_private->setName != nil) {
395 [WebViewSets removeWebView:self fromSetNamed:_private->setName];
396 [_private->setName release];
397 _private->setName = nil;
400 // To avoid leaks, call removeDragCaret in case it wasn't called after moveDragCaretToPoint.
401 [self removeDragCaret];
403 [_private->mainFrame _detachFromParent];
404 [_private->mainFrame release];
405 _private->mainFrame = nil;
407 // Clear the page cache so we call destroy on all the plug-ins in the page cache to break any retain cycles.
408 // See comment in [WebHistoryItem _releaseAllPendingPageCaches] for more information.
409 [_private->backForwardList _clearPageCache];
411 if (_private->hasSpellCheckerDocumentTag) {
412 [[NSSpellChecker sharedSpellChecker] closeSpellDocumentWithTag:_private->spellCheckerDocumentTag];
413 _private->hasSpellCheckerDocumentTag = NO;
417 - (WebFrame *)_createFrameNamed:(NSString *)fname inParent:(WebFrame *)parent allowsScrolling:(BOOL)allowsScrolling
419 WebFrameView *childView = [[WebFrameView alloc] initWithFrame:NSMakeRect(0,0,0,0)];
421 [childView _setWebView:self];
422 [childView setAllowsScrolling:allowsScrolling];
424 WebFrame *newFrame = [[WebFrame alloc] initWithName:fname webFrameView:childView webView:self];
428 [parent _addChild:newFrame];
435 - (void)_finishedLoadingResourceFromDataSource: (WebDataSource *)dataSource
437 WebFrame *frame = [dataSource webFrame];
439 ASSERT(dataSource != nil);
441 // This resource has completed, so check if the load is complete for all frames.
443 [frame _transitionToLayoutAcceptable];
444 [frame _checkLoadComplete];
448 - (void)_mainReceivedBytesSoFar: (unsigned)bytesSoFar fromDataSource: (WebDataSource *)dataSource complete: (BOOL)isComplete
450 WebFrame *frame = [dataSource webFrame];
452 ASSERT(dataSource != nil);
454 // The frame may be nil if a previously cancelled load is still making progress callbacks.
458 // This resource has completed, so check if the load is complete for all frames.
460 // If the load is complete, mark the primary load as done. The primary load is the load
461 // of the main document. Other resources may still be arriving.
462 [dataSource _setPrimaryLoadComplete: YES];
463 [frame _checkLoadComplete];
466 // If the frame isn't complete it might be ready for a layout. Perform that check here.
467 // Note that transitioning a frame to this state doesn't guarantee a layout, rather it
468 // just indicates that an early layout can be performed.
469 if ((int)bytesSoFar > timedLayoutSize)
470 [frame _transitionToLayoutAcceptable];
474 - (void)_receivedError: (NSError *)error fromDataSource: (WebDataSource *)dataSource
476 WebFrame *frame = [dataSource webFrame];
478 [frame _checkLoadComplete];
482 - (void)_mainReceivedError:(NSError *)error fromDataSource:(WebDataSource *)dataSource complete:(BOOL)isComplete
486 ASSERT([dataSource webFrame]);
489 [dataSource _setMainDocumentError: error];
492 [dataSource _setPrimaryLoadComplete:YES];
493 [[dataSource webFrame] _checkLoadComplete];
497 + (NSString *)_MIMETypeForFile:(NSString *)path
499 NSString *extension = [path pathExtension];
500 NSString *MIMEType = nil;
502 // FIXME: This is a workaround to make web archive files work with Foundations that
503 // are too old to know about web archive files. We should remove this before we ship.
504 if ([extension _web_isCaseInsensitiveEqualToString:@"webarchive"]) {
505 return @"application/x-webarchive";
508 // Get the MIME type from the extension.
509 if ([extension length] != 0) {
510 MIMEType = [[NSURLFileTypeMappings sharedMappings] MIMETypeForExtension:extension];
513 // If we can't get a known MIME type from the extension, sniff.
514 if ([MIMEType length] == 0 || [MIMEType isEqualToString:@"application/octet-stream"]) {
515 NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:path];
516 NSData *data = [handle readDataOfLength:GUESS_MIME_TYPE_PEEK_LENGTH];
518 if ([data length] != 0) {
519 MIMEType = [data _web_guessedMIMEType];
521 if ([MIMEType length] == 0) {
522 MIMEType = @"application/octet-stream";
529 - (void)_downloadURL:(NSURL *)URL
531 [self _downloadURL:URL toDirectory:nil];
534 - (void)_downloadURL:(NSURL *)URL toDirectory:(NSString *)directory
538 NSURLRequest *request = [[NSURLRequest alloc] initWithURL:URL];
539 [WebDownload _downloadWithRequest:request
540 delegate:_private->downloadDelegate
541 directory:[directory isAbsolutePath] ? directory : nil];
545 - (BOOL)defersCallbacks
547 return _private->defersCallbacks;
550 - (void)setDefersCallbacks:(BOOL)defers
552 if (defers == _private->defersCallbacks) {
556 _private->defersCallbacks = defers;
557 [_private->mainFrame _defersCallbacksChanged];
560 - (void)_setTopLevelFrameName:(NSString *)name
562 [[self mainFrame] _setName:name];
565 - (WebFrame *)_findFrameInThisWindowNamed:(NSString *)name sourceFrame:(WebFrame *)source
567 return [[self mainFrame] _descendantFrameNamed:name sourceFrame:(WebFrame *)source];
570 - (WebFrame *)_findFrameNamed:(NSString *)name sourceFrame:(WebFrame *)source
572 // Try this WebView first.
573 WebFrame *frame = [self _findFrameInThisWindowNamed:name sourceFrame:source];
579 // Try other WebViews in the same set
580 if (_private->setName != nil) {
581 NSEnumerator *enumerator = [WebViewSets webViewsInSetNamed:_private->setName];
583 while ((webView = [enumerator nextObject]) != nil && frame == nil) {
584 frame = [webView _findFrameInThisWindowNamed:name sourceFrame:source];
591 - (WebView *)_openNewWindowWithRequest:(NSURLRequest *)request
593 id wd = [self UIDelegate];
594 WebView *newWindowWebView = nil;
595 if ([wd respondsToSelector:@selector(webView:createWebViewWithRequest:)])
596 newWindowWebView = [wd webView:self createWebViewWithRequest:request];
598 newWindowWebView = [[WebDefaultUIDelegate sharedUIDelegate] webView:self createWebViewWithRequest: request];
601 [[newWindowWebView _UIDelegateForwarder] webViewShow: newWindowWebView];
603 return newWindowWebView;
606 - (NSMenu *)_menuForElement:(NSDictionary *)element
608 NSArray *defaultMenuItems = [[WebDefaultUIDelegate sharedUIDelegate]
609 webView:self contextMenuItemsForElement:element defaultMenuItems:nil];
610 NSArray *menuItems = defaultMenuItems;
614 if (_private->UIDelegate) {
615 id cd = _private->UIDelegate;
617 if ([cd respondsToSelector:@selector(webView:contextMenuItemsForElement:defaultMenuItems:)])
618 menuItems = [cd webView:self contextMenuItemsForElement:element defaultMenuItems:defaultMenuItems];
621 if (menuItems && [menuItems count] > 0) {
622 menu = [[[NSMenu alloc] init] autorelease];
624 for (i=0; i<[menuItems count]; i++) {
625 [menu addItem:[menuItems objectAtIndex:i]];
632 - (void)_mouseDidMoveOverElement:(NSDictionary *)dictionary modifierFlags:(unsigned)modifierFlags
634 // When the mouse isn't over this view at all, we'll get called with a dictionary of nil over
635 // and over again. So it's a good idea to catch that here and not send multiple calls to the delegate
638 if (dictionary && _private->lastElementWasNonNil) {
639 [[self _UIDelegateForwarder] webView:self mouseDidMoveOverElement:dictionary modifierFlags:modifierFlags];
641 _private->lastElementWasNonNil = dictionary != nil;
644 - (void)_goToItem:(WebHistoryItem *)item withLoadType:(WebFrameLoadType)type
646 // We never go back/forward on a per-frame basis, so the target must be the main frame
647 //ASSERT([item target] == nil || [self _findFrameNamed:[item target]] == [self mainFrame]);
649 // abort any current load if we're going back/forward
650 [[self mainFrame] stopLoading];
651 [[self mainFrame] _goToItem:item withLoadType:type];
654 // Not used now, but could be if we ever store frames in bookmarks or history
655 - (void)_loadItem:(WebHistoryItem *)item
657 WebHistoryItem *newItem = [item copy]; // Makes a deep copy, happily
658 [[self backForwardList] addItem:newItem];
659 [self _goToItem:newItem withLoadType:WebFrameLoadTypeIndexedBackForward];
662 - (void)_loadBackForwardListFromOtherView:(WebView *)otherView
664 // It turns out the right combination of behavior is done with the back/forward load
665 // type. (See behavior matrix at the top of WebFramePrivate.) So we copy all the items
666 // in the back forward list, and go to the current one.
668 WebBackForwardList *bfList = [self backForwardList];
669 ASSERT(![bfList currentItem]); // destination list should be empty
671 WebBackForwardList *otherBFList = [otherView backForwardList];
672 if (![otherBFList currentItem]) {
673 return; // empty back forward list, bail
676 WebHistoryItem *newItemToGoTo = nil;
677 int lastItemIndex = [otherBFList forwardListCount];
679 for (i = -[otherBFList backListCount]; i <= lastItemIndex; i++) {
681 // If this item is showing , save away its current scroll and form state,
682 // since that might have changed since loading and it is normally not saved
683 // until we leave that page.
684 [[otherView mainFrame] _saveDocumentAndScrollState];
686 WebHistoryItem *newItem = [[otherBFList itemAtIndex:i] copy];
687 [bfList addItem:newItem];
689 newItemToGoTo = newItem;
693 [self _goToItem:newItemToGoTo withLoadType:WebFrameLoadTypeIndexedBackForward];
696 - (void)_setFormDelegate: (id<WebFormDelegate>)delegate
698 _private->formDelegate = delegate;
701 - (id<WebFormDelegate>)_formDelegate
703 if (!_private->formDelegate) {
704 // create lazily, to give the client a chance to set one before we bother to alloc the shared one
705 _private->formDelegate = [WebFormDelegate _sharedWebFormDelegate];
707 return _private->formDelegate;
710 - (WebCoreSettings *)_settings
712 return _private->settings;
715 - (void)_updateWebCoreSettingsFromPreferences: (WebPreferences *)preferences
717 [_private->settings setCursiveFontFamily:[preferences cursiveFontFamily]];
718 [_private->settings setDefaultFixedFontSize:[preferences defaultFixedFontSize]];
719 [_private->settings setDefaultFontSize:[preferences defaultFontSize]];
720 [_private->settings setDefaultTextEncoding:[preferences defaultTextEncodingName]];
721 [_private->settings setFantasyFontFamily:[preferences fantasyFontFamily]];
722 [_private->settings setFixedFontFamily:[preferences fixedFontFamily]];
723 [_private->settings setJavaEnabled:[preferences isJavaEnabled]];
724 [_private->settings setJavaScriptEnabled:[preferences isJavaScriptEnabled]];
725 [_private->settings setJavaScriptCanOpenWindowsAutomatically:[preferences javaScriptCanOpenWindowsAutomatically]];
726 [_private->settings setMinimumFontSize:[preferences minimumFontSize]];
727 [_private->settings setMinimumLogicalFontSize:[preferences minimumLogicalFontSize]];
728 [_private->settings setPluginsEnabled:[preferences arePlugInsEnabled]];
729 [_private->settings setSansSerifFontFamily:[preferences sansSerifFontFamily]];
730 [_private->settings setSerifFontFamily:[preferences serifFontFamily]];
731 [_private->settings setStandardFontFamily:[preferences standardFontFamily]];
732 [_private->settings setWillLoadImagesAutomatically:[preferences loadsImagesAutomatically]];
734 if ([preferences userStyleSheetEnabled]) {
735 [_private->settings setUserStyleSheetLocation:[[preferences userStyleSheetLocation] _web_originalDataAsString]];
737 [_private->settings setUserStyleSheetLocation:@""];
739 [_private->settings setShouldPrintBackgrounds:[preferences shouldPrintBackgrounds]];
742 - (void)_preferencesChangedNotification: (NSNotification *)notification
744 WebPreferences *preferences = (WebPreferences *)[notification object];
746 ASSERT(preferences == [self preferences]);
747 if (!_private->userAgentOverridden) {
748 [_private->userAgent release];
749 _private->userAgent = nil;
751 [self _updateWebCoreSettingsFromPreferences: preferences];
754 - _frameLoadDelegateForwarder
756 if (!_private->frameLoadDelegateForwarder)
757 _private->frameLoadDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget: [self frameLoadDelegate] defaultTarget: [WebDefaultFrameLoadDelegate sharedFrameLoadDelegate] templateClass: [WebDefaultFrameLoadDelegate class]];
758 return _private->frameLoadDelegateForwarder;
761 - _resourceLoadDelegateForwarder
763 if (!_private->resourceProgressDelegateForwarder)
764 _private->resourceProgressDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget: [self resourceLoadDelegate] defaultTarget: [WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] templateClass: [WebDefaultResourceLoadDelegate class]];
765 return _private->resourceProgressDelegateForwarder;
768 - (void)_cacheResourceLoadDelegateImplementations
770 WebResourceDelegateImplementationCache *cache = &_private->resourceLoadDelegateImplementations;
771 id delegate = [self resourceLoadDelegate];
773 cache->delegateImplementsDidCancelAuthenticationChallenge = [delegate respondsToSelector:@selector(webView:resource:didCancelAuthenticationChallenge:fromDataSource:)];
774 cache->delegateImplementsDidReceiveAuthenticationChallenge = [delegate respondsToSelector:@selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:)];
775 cache->delegateImplementsDidFinishLoadingFromDataSource = [delegate respondsToSelector:@selector(webView:resource:didFinishLoadingFromDataSource:)];
776 cache->delegateImplementsDidReceiveContentLength = [delegate respondsToSelector:@selector(webView:resource:didReceiveContentLength:fromDataSource:)];
777 cache->delegateImplementsDidReceiveResponse = [delegate respondsToSelector:@selector(webView:resource:didReceiveResponse:fromDataSource:)];
778 cache->delegateImplementsWillSendRequest = [delegate respondsToSelector:@selector(webView:resource:willSendRequest:redirectResponse:fromDataSource:)];
779 cache->delegateImplementsIdentifierForRequest = [delegate respondsToSelector:@selector(webView:identifierForInitialRequest:fromDataSource:)];
782 - (WebResourceDelegateImplementationCache)_resourceLoadDelegateImplementations
784 return _private->resourceLoadDelegateImplementations;
787 - _policyDelegateForwarder
789 if (!_private->policyDelegateForwarder)
790 _private->policyDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget: [self policyDelegate] defaultTarget: [WebDefaultPolicyDelegate sharedPolicyDelegate] templateClass: [WebDefaultPolicyDelegate class]];
791 return _private->policyDelegateForwarder;
794 - _UIDelegateForwarder
796 if (!_private->UIDelegateForwarder)
797 _private->UIDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget: [self UIDelegate] defaultTarget: [WebDefaultUIDelegate sharedUIDelegate] templateClass: [WebDefaultUIDelegate class]];
798 return _private->UIDelegateForwarder;
801 - _editingDelegateForwarder
803 // This can be called during window deallocation by QTMovieView in the QuickTime Cocoa Plug-in.
804 // Not sure if that is a bug or not.
807 if (!_private->editingDelegateForwarder)
808 _private->editingDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget: [self editingDelegate] defaultTarget: [WebDefaultEditingDelegate sharedEditingDelegate] templateClass: [WebDefaultEditingDelegate class]];
809 return _private->editingDelegateForwarder;
812 - (WebFrame *)_frameForDataSource: (WebDataSource *)dataSource fromFrame: (WebFrame *)frame
816 WebFrame *result, *aFrame;
818 if ([frame dataSource] == dataSource)
821 if ([frame provisionalDataSource] == dataSource)
824 // It's safe to use the internal version because we know this
825 // function will not change the set of frames
826 frames = [frame _internalChildFrames];
827 count = [frames count];
828 for (i = 0; i < count; i++){
829 aFrame = [frames objectAtIndex: i];
830 result = [self _frameForDataSource: dataSource fromFrame: aFrame];
839 - (WebFrame *)_frameForDataSource: (WebDataSource *)dataSource
841 WebFrame *frame = [self mainFrame];
843 return [self _frameForDataSource: dataSource fromFrame: frame];
847 - (WebFrame *)_frameForView: (WebFrameView *)aView fromFrame: (WebFrame *)frame
851 WebFrame *result, *aFrame;
853 if ([frame frameView] == aView)
856 // It's safe to use the internal version because we know this
857 // function will not change the set of frames
858 frames = [frame _internalChildFrames];
859 count = [frames count];
860 for (i = 0; i < count; i++){
861 aFrame = [frames objectAtIndex: i];
862 result = [self _frameForView: aView fromFrame: aFrame];
870 - (WebFrame *)_frameForView: (WebFrameView *)aView
872 WebFrame *frame = [self mainFrame];
874 return [self _frameForView: aView fromFrame: frame];
879 [[self _UIDelegateForwarder] webViewClose:self];
882 + (void)_unregisterViewClassAndRepresentationClassForMIMEType:(NSString *)MIMEType;
884 [[WebFrameView _viewTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType];
885 [[WebDataSource _repTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType];
888 + (void)_registerViewClass:(Class)viewClass representationClass:(Class)representationClass forURLScheme:(NSString *)URLScheme;
890 NSString *MIMEType = [self _generatedMIMETypeForURLScheme:URLScheme];
891 [self registerViewClass:viewClass representationClass:representationClass forMIMEType:MIMEType];
893 // This is used to make _representationExistsForURLScheme faster.
894 // Without this set, we'd have to create the MIME type each time.
895 if (schemesWithRepresentationsSet == nil) {
896 schemesWithRepresentationsSet = [[NSMutableSet alloc] init];
898 [schemesWithRepresentationsSet addObject:[[[URLScheme lowercaseString] copy] autorelease]];
901 + (NSString *)_generatedMIMETypeForURLScheme:(NSString *)URLScheme
903 return [@"x-apple-web-kit/" stringByAppendingString:[URLScheme lowercaseString]];
906 + (BOOL)_representationExistsForURLScheme:(NSString *)URLScheme
908 return [schemesWithRepresentationsSet containsObject:[URLScheme lowercaseString]];
911 + (BOOL)_canHandleRequest:(NSURLRequest *)request
913 if ([NSURLConnection canHandleRequest:request]) {
917 // We're always willing to load alternate content for unreachable URLs
918 if ([request _webDataRequestUnreachableURL]) {
922 return [self _representationExistsForURLScheme:[[request URL] scheme]];
925 + (NSString *)_decodeData:(NSData *)data
927 return [WebCoreEncodings decodeData:data];
930 - (void)_pushPerformingProgrammaticFocus
932 _private->programmaticFocusCount++;
935 - (void)_popPerformingProgrammaticFocus
937 _private->programmaticFocusCount--;
940 - (BOOL)_isPerformingProgrammaticFocus
942 return _private->programmaticFocusCount != 0;
945 #define UnknownTotalBytes -1
946 #define WebProgressItemDefaultEstimatedLength 1024*16
948 - (void)_didChangeValueForKey: (NSString *)key
950 LOG (Bindings, "calling didChangeValueForKey: %@", key);
951 [self didChangeValueForKey: key];
954 - (void)_willChangeValueForKey: (NSString *)key
956 LOG (Bindings, "calling willChangeValueForKey: %@", key);
957 [self willChangeValueForKey: key];
960 // Always start progress at INITIAL_PROGRESS_VALUE so it appears progress indicators
961 // will immediately show some progress. This helps provide feedback as soon as a load
963 #define INITIAL_PROGRESS_VALUE 0.1
965 - (void)_resetProgress
967 [_private->progressItems release];
968 _private->progressItems = nil;
969 _private->totalPageAndResourceBytesToLoad = 0;
970 _private->totalBytesReceived = 0;
971 _private->progressValue = 0;
972 _private->lastNotifiedProgressValue = 0;
973 _private->lastNotifiedProgressTime = 0;
974 _private->finalProgressChangedSent = NO;
975 _private->numProgressTrackedFrames = 0;
976 [_private->orginatingProgressFrame release];
977 _private->orginatingProgressFrame = nil;
979 - (void)_progressStarted:(WebFrame *)frame
981 LOG (Progress, "frame %p(%@), _private->numProgressTrackedFrames %d, _private->orginatingProgressFrame %p", frame, [frame name], _private->numProgressTrackedFrames, _private->orginatingProgressFrame);
982 [self _willChangeValueForKey: @"estimatedProgress"];
983 if (_private->numProgressTrackedFrames == 0 || _private->orginatingProgressFrame == frame){
984 [self _resetProgress];
985 _private->progressValue = INITIAL_PROGRESS_VALUE;
986 _private->orginatingProgressFrame = [frame retain];
987 [[NSNotificationCenter defaultCenter] postNotificationName:WebViewProgressStartedNotification object:self];
989 _private->numProgressTrackedFrames++;
990 [self _didChangeValueForKey: @"estimatedProgress"];
993 - (void)_finalProgressComplete
997 // Before resetting progress value be sure to send client a least one notification
998 // with final progress value.
999 if (!_private->finalProgressChangedSent) {
1000 _private->progressValue = 1;
1001 [[NSNotificationCenter defaultCenter] postNotificationName:WebViewProgressEstimateChangedNotification object:self];
1004 [self _resetProgress];
1006 [[NSNotificationCenter defaultCenter] postNotificationName:WebViewProgressFinishedNotification object:self];
1009 - (void)_progressCompleted:(WebFrame *)frame
1011 LOG (Progress, "frame %p(%@), _private->numProgressTrackedFrames %d, _private->orginatingProgressFrame %p", frame, [frame name], _private->numProgressTrackedFrames, _private->orginatingProgressFrame);
1013 if (_private->numProgressTrackedFrames <= 0)
1016 [self _willChangeValueForKey: @"estimatedProgress"];
1018 _private->numProgressTrackedFrames--;
1019 if (_private->numProgressTrackedFrames == 0 ||
1020 (frame == _private->orginatingProgressFrame && _private->numProgressTrackedFrames != 0)){
1021 [self _finalProgressComplete];
1023 [self _didChangeValueForKey: @"estimatedProgress"];
1026 - (void)_incrementProgressForConnectionDelegate:(id)connectionDelegate response:(NSURLResponse *)response;
1028 if (!connectionDelegate)
1031 LOG (Progress, "_private->numProgressTrackedFrames %d, _private->orginatingProgressFrame %p", _private->numProgressTrackedFrames, _private->orginatingProgressFrame);
1033 if (_private->numProgressTrackedFrames <= 0)
1036 WebProgressItem *item = [[WebProgressItem alloc] init];
1041 long long length = [response expectedContentLength];
1043 length = WebProgressItemDefaultEstimatedLength;
1045 item->estimatedLength = length;
1046 _private->totalPageAndResourceBytesToLoad += length;
1048 if (!_private->progressItems)
1049 _private->progressItems = [[NSMutableDictionary alloc] init];
1051 [_private->progressItems _web_setObject:item forUncopiedKey:connectionDelegate];
1055 - (void)_incrementProgressForConnectionDelegate:(id)connectionDelegate data:(NSData *)data
1057 if (!connectionDelegate)
1060 WebProgressItem *item = [_private->progressItems objectForKey:connectionDelegate];
1065 [self _willChangeValueForKey: @"estimatedProgress"];
1067 unsigned bytesReceived = [data length];
1068 double increment = 0, percentOfRemainingBytes;
1069 long long remainingBytes, estimatedBytesForPendingRequests;
1071 item->bytesReceived += bytesReceived;
1072 if (item->bytesReceived > item->estimatedLength){
1073 _private->totalPageAndResourceBytesToLoad += ((item->bytesReceived*2) - item->estimatedLength);
1074 item->estimatedLength = item->bytesReceived*2;
1077 int numPendingOrLoadingRequests = [[self mainFrame] _numPendingOrLoadingRequests:YES];
1078 estimatedBytesForPendingRequests = WebProgressItemDefaultEstimatedLength * numPendingOrLoadingRequests;
1079 remainingBytes = ((_private->totalPageAndResourceBytesToLoad + estimatedBytesForPendingRequests) - _private->totalBytesReceived);
1080 percentOfRemainingBytes = (double)bytesReceived / (double)remainingBytes;
1081 increment = (1.0 - _private->progressValue) * percentOfRemainingBytes;
1083 _private->totalBytesReceived += bytesReceived;
1085 _private->progressValue += increment;
1087 if (_private->progressValue < 0.0)
1088 _private->progressValue = 0.0;
1090 if (_private->progressValue > 1.0)
1091 _private->progressValue = 1.0;
1093 double now = CFAbsoluteTimeGetCurrent();
1094 double notifiedProgressTimeDelta = CFAbsoluteTimeGetCurrent() - _private->lastNotifiedProgressTime;
1095 _private->lastNotifiedProgressTime = now;
1097 LOG (Progress, "_private->progressValue %g, _private->numProgressTrackedFrames %d", _private->progressValue, _private->numProgressTrackedFrames);
1098 double notificationProgressDelta = _private->progressValue - _private->lastNotifiedProgressValue;
1099 if ((notificationProgressDelta >= _private->progressNotificationInterval ||
1100 notifiedProgressTimeDelta >= _private->progressNotificationTimeInterval) &&
1101 _private->numProgressTrackedFrames > 0) {
1102 if (!_private->finalProgressChangedSent) {
1103 if (_private->progressValue == 1)
1104 _private->finalProgressChangedSent = YES;
1105 [[NSNotificationCenter defaultCenter] postNotificationName:WebViewProgressEstimateChangedNotification object:self];
1106 _private->lastNotifiedProgressValue = _private->progressValue;
1110 [self _didChangeValueForKey: @"estimatedProgress"];
1113 - (void)_completeProgressForConnectionDelegate:(id)connectionDelegate
1115 WebProgressItem *item = [_private->progressItems objectForKey:connectionDelegate];
1120 // Adjust the total expected bytes to account for any overage/underage.
1121 long long delta = item->bytesReceived - item->estimatedLength;
1122 _private->totalPageAndResourceBytesToLoad += delta;
1123 item->estimatedLength = item->bytesReceived;
1126 // Required to prevent automatic observer notifications.
1127 + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key {
1131 - (NSArray *)_declaredKeys {
1132 static NSArray *declaredKeys = nil;
1134 if (!declaredKeys) {
1135 declaredKeys = [[NSArray alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey, _WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, nil];
1138 return declaredKeys;
1141 - (void)setObservationInfo:(void *)info
1143 _private->observationInfo = info;
1146 - (void *)observationInfo
1148 return _private->observationInfo;
1151 - (void)_willChangeBackForwardKeys
1153 [self _willChangeValueForKey: _WebCanGoBackKey];
1154 [self _willChangeValueForKey: _WebCanGoForwardKey];
1157 - (void)_didChangeBackForwardKeys
1159 [self _didChangeValueForKey: _WebCanGoBackKey];
1160 [self _didChangeValueForKey: _WebCanGoForwardKey];
1163 - (void)_didStartProvisionalLoadForFrame:(WebFrame *)frame
1165 [self _willChangeBackForwardKeys];
1166 if (frame == [self mainFrame]){
1167 // Force an observer update by sending a will/did.
1168 [self _willChangeValueForKey: _WebIsLoadingKey];
1169 [self _didChangeValueForKey: _WebIsLoadingKey];
1171 [self _willChangeValueForKey: _WebMainFrameURLKey];
1173 [NSApp setWindowsNeedUpdate:YES];
1176 - (void)_didCommitLoadForFrame:(WebFrame *)frame
1178 if (frame == [self mainFrame]){
1179 [self _didChangeValueForKey: _WebMainFrameURLKey];
1181 [NSApp setWindowsNeedUpdate:YES];
1184 - (void)_didFinishLoadForFrame:(WebFrame *)frame
1186 [self _didChangeBackForwardKeys];
1187 if (frame == [self mainFrame]){
1188 // Force an observer update by sending a will/did.
1189 [self _willChangeValueForKey: _WebIsLoadingKey];
1190 [self _didChangeValueForKey: _WebIsLoadingKey];
1192 [NSApp setWindowsNeedUpdate:YES];
1195 - (void)_didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
1197 [self _didChangeBackForwardKeys];
1198 if (frame == [self mainFrame]){
1199 // Force an observer update by sending a will/did.
1200 [self _willChangeValueForKey: _WebIsLoadingKey];
1201 [self _didChangeValueForKey: _WebIsLoadingKey];
1203 [NSApp setWindowsNeedUpdate:YES];
1206 - (void)_didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
1208 [self _didChangeBackForwardKeys];
1209 if (frame == [self mainFrame]){
1210 // Force an observer update by sending a will/did.
1211 [self _willChangeValueForKey: _WebIsLoadingKey];
1212 [self _didChangeValueForKey: _WebIsLoadingKey];
1214 [self _didChangeValueForKey: _WebMainFrameURLKey];
1216 [NSApp setWindowsNeedUpdate:YES];
1219 - (void)_reloadForPluginChanges
1221 [[self mainFrame] _reloadForPluginChanges];
1224 - (NSCachedURLResponse *)_cachedResponseForURL:(NSURL *)URL
1226 NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:URL];
1227 [request setHTTPUserAgent:[self userAgentForURL:URL]];
1228 NSCachedURLResponse *cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:request];
1230 return cachedResponse;
1233 - (void)_writeImageElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
1235 NSURL *linkURL = [element objectForKey:WebElementLinkURLKey];
1236 [pasteboard _web_writeImage:[element objectForKey:WebElementImageKey]
1237 URL:linkURL ? linkURL : [element objectForKey:WebElementImageURLKey]
1238 title:[element objectForKey:WebElementImageAltStringKey]
1239 archive:[[element objectForKey:WebElementDOMNodeKey] webArchive]
1243 - (void)_writeLinkElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
1245 [pasteboard _web_writeURL:[element objectForKey:WebElementLinkURLKey]
1246 andTitle:[element objectForKey:WebElementLinkLabelKey]
1250 - (void)_setInitiatedDrag:(BOOL)initiatedDrag
1252 _private->initiatedDrag = initiatedDrag;
1255 #define DASHBOARD_CONTROL_LABEL @"control"
1257 - (void)_addScrollerDashboardRegions:(NSMutableDictionary *)regions from:(NSArray *)views
1259 // Add scroller regions for NSScroller and KWQScrollBar
1260 int i, count = [views count];
1262 for (i = 0; i < count; i++) {
1263 NSView *aView = [views objectAtIndex:i];
1265 if ([aView isKindOfClass:[NSScroller class]] ||
1266 [aView isKindOfClass:NSClassFromString (@"KWQScrollBar")]) {
1267 NSRect bounds = [aView bounds];
1268 NSRect adjustedBounds;
1269 adjustedBounds.origin = [self convertPoint:bounds.origin fromView:aView];
1270 adjustedBounds.origin.y = [self bounds].size.height - adjustedBounds.origin.y;
1272 // AppKit has horrible hack of placing absent scrollers at -100,-100
1273 if (adjustedBounds.origin.y == -100)
1275 adjustedBounds.size = bounds.size;
1276 NSRect clip = [aView visibleRect];
1277 NSRect adjustedClip;
1278 adjustedClip.origin = [self convertPoint:clip.origin fromView:aView];
1279 adjustedClip.origin.y = [self bounds].size.height - adjustedClip.origin.y;
1280 adjustedClip.size = clip.size;
1281 WebDashboardRegion *aRegion =
1282 [[[WebDashboardRegion alloc] initWithRect:adjustedBounds
1283 clip:adjustedClip type:WebDashboardRegionTypeScrollerRectangle] autorelease];
1284 NSMutableArray *scrollerRegions;
1285 scrollerRegions = [regions objectForKey:DASHBOARD_CONTROL_LABEL];
1286 if (!scrollerRegions) {
1287 scrollerRegions = [NSMutableArray array];
1288 [regions setObject:scrollerRegions forKey:DASHBOARD_CONTROL_LABEL];
1290 [scrollerRegions addObject:aRegion];
1292 [self _addScrollerDashboardRegions:regions from:[aView subviews]];
1296 - (void)_addScrollerDashboardRegions:(NSMutableDictionary *)regions
1298 [self _addScrollerDashboardRegions:regions from:[self subviews]];
1301 - (NSDictionary *)_dashboardRegions
1303 // Only return regions from main frame.
1304 NSMutableDictionary *regions = [[[self mainFrame] _bridge] dashboardRegions];
1305 [self _addScrollerDashboardRegions:regions];
1309 - (void)_setDashboardBehavior:(WebDashboardBehavior)behavior to:(BOOL)flag;
1312 case WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows: {
1313 _private->dashboardBehaviorAlwaysSendMouseEventsToAllWindows = flag;
1316 case WebDashboardBehaviorAlwaysSendActiveNullEventsToPlugIns: {
1317 _private->dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns = flag;
1320 case WebDashboardBehaviorAlwaysAcceptsFirstMouse: {
1321 _private->dashboardBehaviorAlwaysAcceptsFirstMouse = flag;
1324 case WebDashboardBehaviorAllowWheelScrolling: {
1325 _private->dashboardBehaviorAllowWheelScrolling = flag;
1331 - (BOOL)_dashboardBehavior:(WebDashboardBehavior)behavior
1334 case WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows: {
1335 return _private->dashboardBehaviorAlwaysSendMouseEventsToAllWindows;
1337 case WebDashboardBehaviorAlwaysSendActiveNullEventsToPlugIns: {
1338 return _private->dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns;
1340 case WebDashboardBehaviorAlwaysAcceptsFirstMouse: {
1341 return _private->dashboardBehaviorAlwaysAcceptsFirstMouse;
1343 case WebDashboardBehaviorAllowWheelScrolling: {
1344 return _private->dashboardBehaviorAllowWheelScrolling;
1350 - (void)handleAuthenticationForResource:(id)identifier challenge:(NSURLAuthenticationChallenge *)challenge fromDataSource:(WebDataSource *)dataSource
1352 [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:self resource:identifier didReceiveAuthenticationChallenge:challenge fromDataSource:dataSource];
1355 + (void)_setShouldUseFontSmoothing:(BOOL)f
1357 shouldUseFontSmoothing = f;
1360 + (BOOL)_shouldUseFontSmoothing
1362 return shouldUseFontSmoothing;
1368 @implementation _WebSafeForwarder
1370 - initWithTarget: t defaultTarget: dt templateClass: (Class)aClass
1373 target = t; // Non retained.
1375 templateClass = aClass;
1380 // Used to send messages to delegates that implement informal protocols.
1381 + safeForwarderWithTarget: t defaultTarget: dt templateClass: (Class)aClass;
1383 return [[[_WebSafeForwarder alloc] initWithTarget: t defaultTarget: dt templateClass: aClass] autorelease];
1387 NSMutableDictionary *countInvocations;
1390 - (void)forwardInvocation:(NSInvocation *)anInvocation
1393 if (!countInvocations){
1394 countInvocations = [[NSMutableDictionary alloc] init];
1396 NSNumber *count = [countInvocations objectForKey: NSStringFromSelector([anInvocation selector])];
1398 count = [NSNumber numberWithInt: 1];
1400 count = [NSNumber numberWithInt: [count intValue] + 1];
1401 [countInvocations setObject: count forKey: NSStringFromSelector([anInvocation selector])];
1403 if ([target respondsToSelector: [anInvocation selector]])
1404 [anInvocation invokeWithTarget: target];
1405 else if ([defaultTarget respondsToSelector: [anInvocation selector]])
1406 [anInvocation invokeWithTarget: defaultTarget];
1407 // Do nothing quietly if method not implemented.
1410 - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
1412 return [templateClass instanceMethodSignatureForSelector: aSelector];
1417 @implementation WebView
1419 + (BOOL)canShowMIMEType:(NSString *)MIMEType
1421 return [self _viewClass:nil andRepresentationClass:nil forMIMEType:MIMEType];
1424 + (BOOL)canShowMIMETypeAsHTML:(NSString *)MIMEType
1426 return [WebFrameView _canShowMIMETypeAsHTML:MIMEType];
1429 + (NSArray *)MIMETypesShownAsHTML
1431 NSMutableDictionary *viewTypes = [WebFrameView _viewTypesAllowImageTypeOmission:YES];
1432 NSEnumerator *enumerator = [viewTypes keyEnumerator];
1434 NSMutableArray *array = [[[NSMutableArray alloc] init] autorelease];
1436 while ((key = [enumerator nextObject])) {
1437 if ([viewTypes objectForKey:key] == [WebHTMLView class]) {
1438 [array addObject:key];
1445 + (void)setMIMETypesShownAsHTML:(NSArray *)MIMETypes
1447 NSEnumerator *enumerator;
1450 NSMutableDictionary *viewTypes = [WebFrameView _viewTypesAllowImageTypeOmission:YES];
1451 enumerator = [viewTypes keyEnumerator];
1452 while ((key = [enumerator nextObject])) {
1453 if ([viewTypes objectForKey:key] == [WebHTMLView class]) {
1454 [WebView _unregisterViewClassAndRepresentationClassForMIMEType:key];
1458 int i, count = [MIMETypes count];
1459 for (i = 0; i < count; i++) {
1460 [WebView registerViewClass:[WebHTMLView class]
1461 representationClass:[WebHTMLRepresentation class]
1462 forMIMEType:[MIMETypes objectAtIndex:i]];
1466 + (NSURL *)URLFromPasteboard:(NSPasteboard *)pasteboard
1468 return [pasteboard _web_bestURL];
1471 + (NSString *)URLTitleFromPasteboard:(NSPasteboard *)pasteboard
1473 return [pasteboard stringForType:WebURLNamePboardType];
1476 - (void)_registerDraggedTypes
1478 NSArray *editableTypes = [WebHTMLView _insertablePasteboardTypes];
1479 NSArray *URLTypes = [NSPasteboard _web_dragTypesForURL];
1480 NSMutableSet *types = [[NSMutableSet alloc] initWithArray:editableTypes];
1481 [types addObjectsFromArray:URLTypes];
1482 [self registerForDraggedTypes:[types allObjects]];
1486 #if !BUILDING_ON_PANTHER
1487 static bool CGContextInitialized = false;
1490 - (void)_commonInitializationWithFrameName:(NSString *)frameName groupName:(NSString *)groupName
1492 #if !BUILDING_ON_PANTHER
1493 if (!CGContextInitialized) {
1494 CFStringRef key = CFSTR(kCGSDisableDeferredUpdates);
1495 CGSSetConnectionProperty([NSApp contextID], [NSApp contextID], (CGSValueObj)key, (CGSValueObj)kCFBooleanTrue);
1496 CGContextInitialized = true;
1500 _private->drawsBackground = YES;
1501 _private->smartInsertDeleteEnabled = YES;
1503 NSRect f = [self frame];
1504 WebFrameView *wv = [[WebFrameView alloc] initWithFrame: NSMakeRect(0,0,f.size.width,f.size.height)];
1505 [wv setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable];
1506 [self addSubview: wv];
1509 _private->mainFrame = [[WebFrame alloc] initWithName: frameName webFrameView: wv webView: self];
1510 [self setGroupName:groupName];
1512 // If there's already a next key view (e.g., from a nib), wire it up to our
1513 // contained frame view. In any case, wire our next key view up to the our
1514 // contained frame view. This works together with our becomeFirstResponder
1515 // and setNextKeyView overrides.
1516 NSView *nextKeyView = [self nextKeyView];
1517 if (nextKeyView != nil && nextKeyView != wv) {
1518 [wv setNextKeyView:nextKeyView];
1520 [super setNextKeyView:wv];
1524 [self _registerDraggedTypes];
1526 // Update WebCore with preferences. These values will either come from an archived WebPreferences,
1527 // or from the standard preferences, depending on whether this method was called from initWithCoder:
1528 // or initWithFrame, respectively.
1529 [self _updateWebCoreSettingsFromPreferences: [self preferences]];
1531 // Register to receive notifications whenever preference values change.
1532 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:)
1533 name:WebPreferencesChangedNotification object:[self preferences]];
1538 return [self initWithFrame: NSZeroRect frameName: nil groupName: nil];
1541 - initWithFrame: (NSRect)f
1543 [self initWithFrame: f frameName:nil groupName:nil];
1547 - initWithFrame: (NSRect)f frameName: (NSString *)frameName groupName: (NSString *)groupName;
1549 [super initWithFrame: f];
1550 _private = [[WebViewPrivate alloc] init];
1551 [self _commonInitializationWithFrameName:frameName groupName:groupName];
1552 [self setMaintainsBackForwardList: YES];
1556 - (id)initWithCoder:(NSCoder *)decoder
1558 WebView *result = nil;
1562 NSString *frameName;
1563 NSString *groupName;
1565 result = [super initWithCoder:decoder];
1566 result->_private = [[WebViewPrivate alloc] init];
1568 // We don't want any of the archived subviews. The subviews will always
1569 // be created in _commonInitializationFrameName:groupName:.
1570 [[result subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
1572 if ([decoder allowsKeyedCoding]){
1573 frameName = [decoder decodeObjectForKey:@"FrameName"];
1574 groupName = [decoder decodeObjectForKey:@"GroupName"];
1576 [result setPreferences: [decoder decodeObjectForKey:@"Preferences"]];
1577 result->_private->useBackForwardList = [decoder decodeBoolForKey:@"UseBackForwardList"];
1579 LOG (Encoding, "FrameName = %@, GroupName = %@, useBackForwardList = %d\n", frameName, groupName, (int)_private->useBackForwardList);
1584 [decoder decodeValueOfObjCType:@encode(int) at:&version];
1585 frameName = [decoder decodeObject];
1586 groupName = [decoder decodeObject];
1587 [result setPreferences: [decoder decodeObject]];
1589 [decoder decodeValuesOfObjCTypes:"c",&result->_private->useBackForwardList];
1591 [result _commonInitializationWithFrameName:frameName groupName:groupName];
1603 - (void)encodeWithCoder:(NSCoder *)encoder
1605 [super encodeWithCoder:encoder];
1607 if ([encoder allowsKeyedCoding]){
1608 [encoder encodeObject:[[self mainFrame] name] forKey:@"FrameName"];
1609 [encoder encodeObject:[self groupName] forKey:@"GroupName"];
1610 [encoder encodeObject:[self preferences] forKey:@"Preferences"];
1611 [encoder encodeBool:_private->useBackForwardList forKey:@"UseBackForwardList"];
1613 LOG (Encoding, "FrameName = %@, GroupName = %@, useBackForwardList = %d\n", [[self mainFrame] name], [self groupName], (int)_private->useBackForwardList);
1616 int version = WebViewVersion;
1617 [encoder encodeValueOfObjCType:@encode(int) at:&version];
1618 [encoder encodeObject:[[self mainFrame] name]];
1619 [encoder encodeObject:[self groupName]];
1620 [encoder encodeObject:[self preferences]];
1621 [encoder encodeValuesOfObjCTypes:"c",&_private->useBackForwardList];
1631 [[NSNotificationCenter defaultCenter] removeObserver:self];
1633 [WebPreferences _removeReferenceForIdentifier: [self preferencesIdentifier]];
1636 // [super dealloc] can end up dispatching against _private (3466082)
1648 [[NSNotificationCenter defaultCenter] removeObserver:self];
1650 [WebPreferences _removeReferenceForIdentifier: [self preferencesIdentifier]];
1655 - (void)setPreferences: (WebPreferences *)prefs
1657 if (_private->preferences != prefs){
1658 [[NSNotificationCenter defaultCenter] removeObserver: self name: WebPreferencesChangedNotification object: [self preferences]];
1659 [WebPreferences _removeReferenceForIdentifier: [_private->preferences identifier]];
1660 [_private->preferences release];
1661 _private->preferences = [prefs retain];
1662 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:)
1663 name:WebPreferencesChangedNotification object:[self preferences]];
1665 [[NSNotificationCenter defaultCenter]
1666 postNotificationName:WebPreferencesChangedNotification object:prefs userInfo:nil];
1670 - (WebPreferences *)preferences
1672 return _private->preferences ? _private->preferences : [WebPreferences standardPreferences];
1675 - (void)setPreferencesIdentifier:(NSString *)anIdentifier
1677 if (![anIdentifier isEqual: [[self preferences] identifier]]){
1678 [self setPreferences: [[WebPreferences alloc] initWithIdentifier:anIdentifier]];
1682 - (NSString *)preferencesIdentifier
1684 return [[self preferences] identifier];
1688 - (void)setUIDelegate:delegate
1690 _private->UIDelegate = delegate;
1691 [_private->UIDelegateForwarder release];
1692 _private->UIDelegateForwarder = nil;
1697 return _private->UIDelegate;
1700 - (void)setResourceLoadDelegate: delegate
1702 _private->resourceProgressDelegate = delegate;
1703 [_private->resourceProgressDelegateForwarder release];
1704 _private->resourceProgressDelegateForwarder = nil;
1705 [self _cacheResourceLoadDelegateImplementations];
1709 - resourceLoadDelegate
1711 return _private->resourceProgressDelegate;
1715 - (void)setDownloadDelegate: delegate
1717 _private->downloadDelegate = delegate;
1723 return _private->downloadDelegate;
1726 - (void)setPolicyDelegate:delegate
1728 _private->policyDelegate = delegate;
1729 [_private->policyDelegateForwarder release];
1730 _private->policyDelegateForwarder = nil;
1735 return _private->policyDelegate;
1738 - (void)setFrameLoadDelegate:delegate
1740 _private->frameLoadDelegate = delegate;
1741 [_private->frameLoadDelegateForwarder release];
1742 _private->frameLoadDelegateForwarder = nil;
1747 return _private->frameLoadDelegate;
1750 - (WebFrame *)mainFrame
1752 // This can be called in initialization, before _private has been set up (3465613)
1753 if (_private != nil) {
1754 return _private->mainFrame;
1759 - (WebBackForwardList *)backForwardList
1761 if (_private->useBackForwardList)
1762 return _private->backForwardList;
1766 - (void)setMaintainsBackForwardList: (BOOL)flag
1768 _private->useBackForwardList = flag;
1773 WebHistoryItem *item = [[self backForwardList] backItem];
1776 [self _goToItem: item withLoadType: WebFrameLoadTypeBack];
1784 WebHistoryItem *item = [[self backForwardList] forwardItem];
1787 [self _goToItem: item withLoadType: WebFrameLoadTypeForward];
1793 - (BOOL)goToBackForwardItem:(WebHistoryItem *)item
1795 [self _goToItem: item withLoadType: WebFrameLoadTypeIndexedBackForward];
1799 - (void)setTextSizeMultiplier:(float)m
1801 if (_private->textSizeMultiplier == m) {
1804 _private->textSizeMultiplier = m;
1805 [[self mainFrame] _textSizeMultiplierChanged];
1808 - (float)textSizeMultiplier
1810 return _private->textSizeMultiplier;
1813 - (void)setApplicationNameForUserAgent:(NSString *)applicationName
1815 NSString *name = [applicationName copy];
1816 [_private->applicationNameForUserAgent release];
1817 _private->applicationNameForUserAgent = name;
1818 if (!_private->userAgentOverridden) {
1819 [_private->userAgent release];
1820 _private->userAgent = nil;
1824 - (NSString *)applicationNameForUserAgent
1826 return [[_private->applicationNameForUserAgent retain] autorelease];
1829 - (void)setCustomUserAgent:(NSString *)userAgentString
1831 NSString *override = [userAgentString copy];
1832 [_private->userAgent release];
1833 _private->userAgent = override;
1834 _private->userAgentOverridden = override != nil;
1837 - (NSString *)customUserAgent
1839 return _private->userAgentOverridden ? [[_private->userAgent retain] autorelease] : nil;
1842 - (void)setMediaStyle:(NSString *)mediaStyle
1844 if (_private->mediaStyle != mediaStyle) {
1845 [_private->mediaStyle release];
1846 _private->mediaStyle = [mediaStyle copy];
1850 - (NSString *)mediaStyle
1852 return _private->mediaStyle;
1855 - (BOOL)supportsTextEncoding
1857 id documentView = [[[self mainFrame] frameView] documentView];
1858 return [documentView conformsToProtocol:@protocol(WebDocumentText)]
1859 && [documentView supportsTextEncoding];
1862 - (void)setCustomTextEncodingName:(NSString *)encoding
1864 NSString *oldEncoding = [self customTextEncodingName];
1865 if (encoding == oldEncoding || [encoding isEqualToString:oldEncoding]) {
1868 [[self mainFrame] _reloadAllowingStaleDataWithOverrideEncoding:encoding];
1871 - (NSString *)_mainFrameOverrideEncoding
1873 WebDataSource *dataSource = [[self mainFrame] provisionalDataSource];
1874 if (dataSource == nil) {
1875 dataSource = [[self mainFrame] dataSource];
1877 if (dataSource == nil) {
1880 return [dataSource _overrideEncoding];
1883 - (NSString *)customTextEncodingName
1885 return [self _mainFrameOverrideEncoding];
1888 - (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script
1890 return [[[self mainFrame] _bridge] stringByEvaluatingJavaScriptFromString:script];
1893 - (WebScriptObject *)windowScriptObject
1895 return [[[self mainFrame] _bridge] windowScriptObject];
1899 // Get the appropriate user-agent string for a particular URL.
1900 // Since we no longer automatically spoof, this no longer requires looking at the URL.
1901 - (NSString *)userAgentForURL:(NSURL *)URL
1903 NSString *userAgent = _private->userAgent;
1905 return [[userAgent retain] autorelease];
1908 // FIXME: Some day we will start reporting the actual CPU here instead of hardcoding PPC.
1910 NSString *language = [NSUserDefaults _web_preferredLanguageCode];
1911 id sourceVersion = [[NSBundle bundleForClass:[WebView class]]
1912 objectForInfoDictionaryKey:(id)kCFBundleVersionKey];
1913 NSString *applicationName = _private->applicationNameForUserAgent;
1915 if ([applicationName length]) {
1916 userAgent = [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; U; PPC Mac OS X; %@) AppleWebKit/%@ (KHTML, like Gecko) %@",
1917 language, sourceVersion, applicationName];
1919 userAgent = [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; U; PPC Mac OS X; %@) AppleWebKit/%@ (KHTML, like Gecko)",
1920 language, sourceVersion];
1923 _private->userAgent = [userAgent retain];
1927 - (void)setHostWindow:(NSWindow *)hostWindow
1929 if (hostWindow != _private->hostWindow) {
1930 [[self mainFrame] _viewWillMoveToHostWindow:hostWindow];
1931 [_private->hostWindow release];
1932 _private->hostWindow = [hostWindow retain];
1933 [[self mainFrame] _viewDidMoveToHostWindow];
1937 - (NSWindow *)hostWindow
1939 return _private->hostWindow;
1942 - (NSView <WebDocumentView> *)documentViewAtWindowPoint:(NSPoint)point
1944 return [[self _frameViewAtWindowPoint:point] documentView];
1947 - (NSView <WebDocumentDragging> *)_draggingDocumentViewAtWindowPoint:(NSPoint)point
1949 NSView <WebDocumentView> *documentView = [self documentViewAtWindowPoint:point];
1950 if ([documentView conformsToProtocol:@protocol(WebDocumentDragging)]) {
1951 return (NSView <WebDocumentDragging> *)documentView;
1956 - (NSDictionary *)_elementAtWindowPoint:(NSPoint)windowPoint
1958 WebFrameView *frameView = [self _frameViewAtWindowPoint:windowPoint];
1961 NSView <WebDocumentView> *documentView = [frameView documentView];
1962 if ([documentView conformsToProtocol:@protocol(WebDocumentElement)]) {
1963 NSPoint point = [documentView convertPoint:windowPoint fromView:nil];
1964 return [(NSView <WebDocumentElement> *)documentView elementAtPoint:point];
1966 return [NSDictionary dictionaryWithObject:[frameView webFrame] forKey:WebElementFrameKey];
1969 - (NSDictionary *)elementAtPoint:(NSPoint)point
1971 return [self _elementAtWindowPoint:[self convertPoint:point toView:nil]];
1974 - (void)_setDraggingDocumentView:(NSView <WebDocumentDragging> *)newDraggingView
1976 if (_private->draggingDocumentView != newDraggingView) {
1977 [_private->draggingDocumentView release];
1978 _private->draggingDocumentView = [newDraggingView retain];
1982 - (NSDragOperation)_loadingDragOperationForDraggingInfo:(id <NSDraggingInfo>)draggingInfo
1984 if (_private->dragDestinationActionMask & WebDragDestinationActionLoad) {
1985 NSPoint windowPoint = [draggingInfo draggingLocation];
1986 NSView *view = [self hitTest:[[self superview] convertPoint:windowPoint toView:nil]];
1987 // Don't accept the drag over a plug-in since plug-ins may want to handle it.
1988 if (![view isKindOfClass:[WebBaseNetscapePluginView class]] && !_private->editable && !_private->initiatedDrag) {
1989 // If not editing or dragging, use _web_dragOperationForDraggingInfo to find a URL to load on the pasteboard.
1990 return [self _web_dragOperationForDraggingInfo:draggingInfo];
1993 return NSDragOperationNone;
1996 - (NSDragOperation)_delegateDragOperationForDraggingInfo:(id <NSDraggingInfo>)draggingInfo
1998 NSPoint windowPoint = [draggingInfo draggingLocation];
1999 NSView <WebDocumentDragging> *newDraggingView = [self _draggingDocumentViewAtWindowPoint:windowPoint];
2000 if (_private->draggingDocumentView != newDraggingView) {
2001 [_private->draggingDocumentView draggingCancelledWithDraggingInfo:draggingInfo];
2002 [self _setDraggingDocumentView:newDraggingView];
2005 _private->dragDestinationActionMask = [[self _UIDelegateForwarder] webView:self dragDestinationActionMaskForDraggingInfo:draggingInfo];
2006 NSDragOperation operation = NSDragOperationNone;
2008 if (_private->dragDestinationActionMask == WebDragDestinationActionNone) {
2009 [_private->draggingDocumentView draggingCancelledWithDraggingInfo:draggingInfo];
2011 operation = [_private->draggingDocumentView draggingUpdatedWithDraggingInfo:draggingInfo actionMask:_private->dragDestinationActionMask];
2012 if (operation == NSDragOperationNone) {
2013 return [self _loadingDragOperationForDraggingInfo:draggingInfo];
2020 // The following 2 internal NSView methods are called on the drag destination by make scrolling while dragging work.
2021 // Scrolling while dragging will only work if the drag destination is in a scroll view. The WebView is the drag destination.
2022 // When dragging to a WebView, the document subview should scroll, but it doesn't because it is not the drag destination.
2023 // Forward these calls to the document subview to make its scroll view scroll.
2024 - (void)_autoscrollForDraggingInfo:(id)draggingInfo timeDelta:(NSTimeInterval)repeatDelta
2026 NSView <WebDocumentView> *documentView = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
2027 [documentView _autoscrollForDraggingInfo:draggingInfo timeDelta:repeatDelta];
2030 - (BOOL)_shouldAutoscrollForDraggingInfo:(id)draggingInfo
2032 NSView <WebDocumentView> *documentView = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
2033 return [documentView _shouldAutoscrollForDraggingInfo:draggingInfo];
2036 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)draggingInfo
2038 return [self _delegateDragOperationForDraggingInfo:draggingInfo];
2041 - (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)draggingInfo
2043 return [self _delegateDragOperationForDraggingInfo:draggingInfo];
2046 - (void)draggingExited:(id <NSDraggingInfo>)draggingInfo
2048 [_private->draggingDocumentView draggingCancelledWithDraggingInfo:draggingInfo];
2049 [self _setDraggingDocumentView:nil];
2052 - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)draggingInfo
2057 - (BOOL)performDragOperation:(id <NSDraggingInfo>)draggingInfo
2059 ASSERT(_private->draggingDocumentView == [self _draggingDocumentViewAtWindowPoint:[draggingInfo draggingLocation]]);
2061 if ([_private->draggingDocumentView concludeDragForDraggingInfo:draggingInfo actionMask:_private->dragDestinationActionMask]) {
2062 [self _setDraggingDocumentView:nil];
2066 [self _setDraggingDocumentView:nil];
2068 if ([self _loadingDragOperationForDraggingInfo:draggingInfo] != NSDragOperationNone) {
2069 NSURL *URL = [[self class] URLFromPasteboard:[draggingInfo draggingPasteboard]];
2071 [[self _UIDelegateForwarder] webView:self willPerformDragDestinationAction:WebDragDestinationActionLoad forDraggingInfo:draggingInfo];
2072 NSURLRequest *request = [[NSURLRequest alloc] initWithURL:URL];
2073 [[self mainFrame] loadRequest:request];
2082 - (NSView *)_hitTest:(NSPoint *)aPoint dragTypes:(NSSet *)types
2084 NSView *hitView = [super _hitTest:aPoint dragTypes:types];
2085 if (!hitView && [[self superview] mouse:*aPoint inRect:[self frame]]) {
2092 - (BOOL)acceptsFirstResponder
2094 return [[[self mainFrame] frameView] acceptsFirstResponder];
2097 - (BOOL)becomeFirstResponder
2099 // This works together with setNextKeyView to splice the WebView into
2100 // the key loop similar to the way NSScrollView does this. Note that
2101 // WebFrameView has very similar code.
2102 NSWindow *window = [self window];
2103 WebFrameView *mainFrameView = [[self mainFrame] frameView];
2105 if ([window keyViewSelectionDirection] == NSSelectingPrevious) {
2106 NSView *previousValidKeyView = [self previousValidKeyView];
2107 if ((previousValidKeyView != self) && (previousValidKeyView != mainFrameView)) {
2108 [window makeFirstResponder:previousValidKeyView];
2115 if ([mainFrameView acceptsFirstResponder]) {
2116 [window makeFirstResponder:mainFrameView];
2123 - (NSView *)_webcore_effectiveFirstResponder
2125 WebFrameView *frameView = [[self mainFrame] frameView];
2126 return frameView ? [frameView _webcore_effectiveFirstResponder] : [super _webcore_effectiveFirstResponder];
2129 - (void)setNextKeyView:(NSView *)aView
2131 // This works together with becomeFirstResponder to splice the WebView into
2132 // the key loop similar to the way NSScrollView does this. Note that
2133 // WebFrameView has very similar code.
2134 WebFrameView *mainFrameView = [[self mainFrame] frameView];
2135 if (mainFrameView != nil) {
2136 [mainFrameView setNextKeyView:aView];
2138 [super setNextKeyView:aView];
2142 static WebFrame *incrementFrame(WebFrame *curr, BOOL forward, BOOL wrapFlag)
2144 return forward ? [curr _nextFrameWithWrap:wrapFlag]
2145 : [curr _previousFrameWithWrap:wrapFlag];
2148 // Search from the end of the currently selected location, or from the beginning of the
2149 // document if nothing is selected. Deals with subframes.
2150 - (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag
2152 // Get the frame holding the selection, or start with the main frame
2153 WebFrame *startFrame = [self _frameForCurrentSelection];
2155 // Search the first frame, then all the other frames, in order
2156 NSView <WebDocumentSearching> *startSearchView = nil;
2157 BOOL startHasSelection = NO;
2158 WebFrame *frame = startFrame;
2160 id <WebDocumentView> view = [[frame frameView] documentView];
2161 if ([view conformsToProtocol:@protocol(WebDocumentSearching)]) {
2162 NSView <WebDocumentSearching> *searchView = (NSView <WebDocumentSearching> *)view;
2164 // first time through
2165 if (frame == startFrame) {
2166 // Remember if start even has a selection, to know if we need to search more later
2167 if ([searchView isKindOfClass:[WebHTMLView class]]) {
2168 // optimization for the common case, to avoid making giant string for selection
2169 startHasSelection = [[startFrame _bridge] selectedDOMRange] != nil;
2170 } else if ([searchView conformsToProtocol:@protocol(WebDocumentText)]) {
2171 startHasSelection = [(id <WebDocumentText>)searchView selectedString] != nil;
2173 startSearchView = searchView;
2176 // Note at this point we are assuming the search will be done top-to-bottom,
2177 // not starting at any selection that exists. See 3228554.
2178 BOOL success = [searchView searchFor:string direction:forward caseSensitive:caseFlag wrap:NO];
2180 [[self window] makeFirstResponder:searchView];
2184 frame = incrementFrame(frame, forward, wrapFlag);
2185 } while (frame != nil && frame != startFrame);
2187 // Search contents of startFrame, on the other side of the selection that we did earlier.
2188 // We cheat a bit and just research with wrap on
2189 if (wrapFlag && startHasSelection && startSearchView) {
2190 BOOL success = [startSearchView searchFor:string direction:forward caseSensitive:caseFlag wrap:YES];
2192 [[self window] makeFirstResponder:startSearchView];
2199 + (void)registerViewClass:(Class)viewClass representationClass:(Class)representationClass forMIMEType:(NSString *)MIMEType
2201 [[WebFrameView _viewTypesAllowImageTypeOmission:YES] setObject:viewClass forKey:MIMEType];
2202 [[WebDataSource _repTypesAllowImageTypeOmission:YES] setObject:representationClass forKey:MIMEType];
2205 - (void)setGroupName:(NSString *)groupName
2207 if (groupName != _private->setName){
2208 [_private->setName release];
2209 _private->setName = [groupName copy];
2210 [WebViewSets addWebView:self toSetNamed:_private->setName];
2214 - (NSString *)groupName
2216 return _private->setName;
2219 - (double)estimatedProgress
2221 return _private->progressValue;
2224 - (NSArray *)pasteboardTypesForSelection
2226 NSView <WebDocumentView> *documentView = [[[self _frameForCurrentSelection] frameView] documentView];
2227 if ([documentView conformsToProtocol:@protocol(WebDocumentSelection)]) {
2228 return [(NSView <WebDocumentSelection> *)documentView pasteboardTypesForSelection];
2230 return [NSArray array];
2233 - (void)writeSelectionWithPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
2235 WebBridge *bridge = [self _bridgeForCurrentSelection];
2236 if ([bridge selectionState] != WebSelectionStateRange) {
2237 NSView <WebDocumentView> *documentView = [[[bridge webFrame] frameView] documentView];
2238 if ([documentView conformsToProtocol:@protocol(WebDocumentSelection)]) {
2239 [(NSView <WebDocumentSelection> *)documentView writeSelectionWithPasteboardTypes:types toPasteboard:pasteboard];
2244 - (NSArray *)pasteboardTypesForElement:(NSDictionary *)element
2246 if ([element objectForKey:WebElementImageURLKey] != nil) {
2247 return [NSPasteboard _web_writableTypesForImageIncludingArchive:([element objectForKey:WebElementDOMNodeKey] != nil)];
2248 } else if ([element objectForKey:WebElementLinkURLKey] != nil) {
2249 return [NSPasteboard _web_writableTypesForURL];
2250 } else if ([[element objectForKey:WebElementIsSelectedKey] boolValue]) {
2251 return [self pasteboardTypesForSelection];
2253 return [NSArray array];
2256 - (void)writeElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
2258 if ([element objectForKey:WebElementImageURLKey] != nil) {
2259 [self _writeImageElement:element withPasteboardTypes:types toPasteboard:pasteboard];
2260 } else if ([element objectForKey:WebElementLinkURLKey] != nil) {
2261 [self _writeLinkElement:element withPasteboardTypes:types toPasteboard:pasteboard];
2262 } else if ([[element objectForKey:WebElementIsSelectedKey] boolValue]) {
2263 [self writeSelectionWithPasteboardTypes:types toPasteboard:pasteboard];
2267 - (void)moveDragCaretToPoint:(NSPoint)point
2269 WebBridge *bridge = [self _bridgeAtPoint:point];
2270 if (bridge != _private->dragCaretBridge) {
2271 [_private->dragCaretBridge removeDragCaret];
2272 _private->dragCaretBridge = [bridge retain];
2274 [_private->dragCaretBridge moveDragCaretToPoint:[self convertPoint:point toView:[[[_private->dragCaretBridge webFrame] frameView] documentView]]];
2277 - (void)removeDragCaret
2279 [_private->dragCaretBridge removeDragCaret];
2280 [_private->dragCaretBridge release];
2281 _private->dragCaretBridge = nil;
2286 @implementation WebView (WebIBActions)
2288 - (IBAction)takeStringURLFrom: sender
2290 NSString *URLString = [sender stringValue];
2292 [[self mainFrame] loadRequest: [NSURLRequest requestWithURL: [NSURL _web_URLWithDataAsString: URLString]]];
2297 return [[self backForwardList] backItem] != nil;
2300 - (BOOL)canGoForward
2302 return [[self backForwardList] forwardItem] != nil;
2305 - (IBAction)goBack:(id)sender
2310 - (IBAction)goForward:(id)sender
2315 - (IBAction)stopLoading:(id)sender
2317 [[self mainFrame] stopLoading];
2320 - (IBAction)reload:(id)sender
2322 [[self mainFrame] reload];
2325 #define MinimumTextSizeMultiplier 0.5
2326 #define MaximumTextSizeMultiplier 3.0
2327 #define TextSizeMultiplierRatio 1.2
2329 - (BOOL)canMakeTextSmaller
2331 if ([[self mainFrame] dataSource] == nil) {
2334 // FIXME: This will prevent text sizing in subframes if the main frame doesn't support it
2335 if (![[[[self mainFrame] frameView] documentView] conformsToProtocol:@protocol(_web_WebDocumentTextSizing)]) {
2338 if ([self textSizeMultiplier]/TextSizeMultiplierRatio < MinimumTextSizeMultiplier) {
2344 - (BOOL)canMakeTextLarger
2346 if ([[self mainFrame] dataSource] == nil) {
2349 // FIXME: This will prevent text sizing in subframes if the main frame doesn't support it
2350 if (![[[[self mainFrame] frameView] documentView] conformsToProtocol:@protocol(_web_WebDocumentTextSizing)]) {
2353 if ([self textSizeMultiplier]*TextSizeMultiplierRatio > MaximumTextSizeMultiplier) {
2359 - (IBAction)makeTextSmaller:(id)sender
2361 if (![self canMakeTextSmaller]) {
2364 [self setTextSizeMultiplier:[self textSizeMultiplier]/TextSizeMultiplierRatio];
2367 - (IBAction)makeTextLarger:(id)sender
2369 if (![self canMakeTextLarger]) {
2372 [self setTextSizeMultiplier:[self textSizeMultiplier]*TextSizeMultiplierRatio];
2375 - (BOOL)_responderValidateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item
2377 id responder = [self _responderForResponderOperations];
2378 if (responder != self && [responder respondsToSelector:[item action]]) {
2379 if ([responder respondsToSelector:@selector(validateUserInterfaceItem:)]) {
2380 return [responder validateUserInterfaceItem:item];
2387 #define VALIDATE(name) \
2388 else if (action == @selector(name:)) { return [self _responderValidateUserInterfaceItem:item]; }
2390 - (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item
2392 SEL action = [item action];
2394 if (action == @selector(goBack:)) {
2395 return [self canGoBack];
2396 } else if (action == @selector(goForward:)) {
2397 return [self canGoForward];
2398 } else if (action == @selector(makeTextLarger:)) {
2399 return [self canMakeTextLarger];
2400 } else if (action == @selector(makeTextSmaller:)) {
2401 return [self canMakeTextSmaller];
2402 } else if (action == @selector(reload:)) {
2403 return [[self mainFrame] dataSource] != nil;
2404 } else if (action == @selector(stopLoading:)) {
2405 return [self _isLoading];
2406 } else if (action == @selector(toggleContinuousSpellChecking:)) {
2407 BOOL checkMark = NO;
2409 if ([self isEditable] && [self _continuousCheckingAllowed]) {
2410 checkMark = [self isContinuousSpellCheckingEnabled];
2413 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
2414 NSMenuItem *menuItem = (NSMenuItem *)item;
2415 [menuItem setState:checkMark ? NSOnState : NSOffState];
2419 FOR_EACH_RESPONDER_SELECTOR(VALIDATE)
2426 @implementation WebView (WebPendingPublic)
2428 - (void)setMainFrameURL:(NSString *)URLString
2430 [[self mainFrame] loadRequest: [NSURLRequest requestWithURL: [NSURL _web_URLWithDataAsString: URLString]]];
2433 - (NSString *)mainFrameURL
2436 ds = [[self mainFrame] provisionalDataSource];
2438 ds = [[self mainFrame] dataSource];
2439 return [[[ds request] URL] _web_originalDataAsString];
2444 LOG (Bindings, "isLoading = %d", (int)[self _isLoading]);
2445 return [self _isLoading];
2448 - (NSString *)mainFrameTitle
2450 NSString *mainFrameTitle = [[[self mainFrame] dataSource] pageTitle];
2451 return (mainFrameTitle != nil) ? mainFrameTitle : @"";
2454 - (NSImage *)mainFrameIcon
2456 return [[WebIconDatabase sharedIconDatabase] iconForURL:[[[[self mainFrame] dataSource] _URL] _web_originalDataAsString] withSize:WebIconSmallSize];
2459 - (void)setDrawsBackground:(BOOL)drawsBackground
2461 if (_private->drawsBackground == drawsBackground)
2463 _private->drawsBackground = drawsBackground;
2464 [[self mainFrame] _updateDrawsBackground];
2467 - (BOOL)drawsBackground
2469 return _private->drawsBackground;
2472 - (void)toggleSmartInsertDelete:(id)sender
2474 if ([self isEditable]) {
2475 [self setSmartInsertDeleteEnabled:![self smartInsertDeleteEnabled]];
2479 - (IBAction)toggleContinuousSpellChecking:(id)sender
2481 if ([self isEditable]) {
2482 [self setContinuousSpellCheckingEnabled:![self isContinuousSpellCheckingEnabled]];
2486 - (BOOL)isContinuousGrammarCheckingEnabled
2488 return _private->continuousGrammarCheckingEnabled && [self _continuousCheckingAllowed];
2491 - (void)setContinuousGrammarCheckingEnabled:(BOOL)flag
2493 _private->continuousGrammarCheckingEnabled = flag;
2494 if ([self isContinuousGrammarCheckingEnabled]) {
2495 [self _preflightSpellChecker];
2497 // FIXME: Put code here to remove underlines for bad grammar.
2501 - (void)toggleContinuousGrammarChecking:(id)sender
2503 if ([self isEditable]) {
2504 [self setContinuousGrammarCheckingEnabled:![self isContinuousGrammarCheckingEnabled]];
2510 @implementation WebView (WebViewPrintingPrivate)
2512 - (float)_headerHeight
2514 if ([[self UIDelegate] respondsToSelector:@selector(webViewHeaderHeight:)]) {
2515 return [[self UIDelegate] webViewHeaderHeight:self];
2518 #ifdef DEBUG_HEADER_AND_FOOTER
2525 - (float)_footerHeight
2527 if ([[self UIDelegate] respondsToSelector:@selector(webViewFooterHeight:)]) {
2528 return [[self UIDelegate] webViewFooterHeight:self];
2531 #ifdef DEBUG_HEADER_AND_FOOTER
2538 - (void)_drawHeaderInRect:(NSRect)rect
2540 #ifdef DEBUG_HEADER_AND_FOOTER
2541 NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
2542 [currentContext saveGraphicsState];
2543 [[NSColor yellowColor] set];
2545 [currentContext restoreGraphicsState];
2548 if ([[self UIDelegate] respondsToSelector:@selector(webView:drawHeaderInRect:)]) {
2549 NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
2550 [currentContext saveGraphicsState];
2552 [[self UIDelegate] webView:self drawHeaderInRect:rect];
2553 [currentContext restoreGraphicsState];
2557 - (void)_drawFooterInRect:(NSRect)rect
2559 #ifdef DEBUG_HEADER_AND_FOOTER
2560 NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
2561 [currentContext saveGraphicsState];
2562 [[NSColor cyanColor] set];
2564 [currentContext restoreGraphicsState];
2567 if ([[self UIDelegate] respondsToSelector:@selector(webView:drawFooterInRect:)]) {
2568 NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
2569 [currentContext saveGraphicsState];
2571 [[self UIDelegate] webView:self drawFooterInRect:rect];
2572 [currentContext restoreGraphicsState];
2576 - (void)_adjustPrintingMarginsForHeaderAndFooter
2578 NSPrintOperation *op = [NSPrintOperation currentOperation];
2579 NSPrintInfo *info = [op printInfo];
2580 float scale = [op _web_pageSetupScaleFactor];
2581 [info setTopMargin:[info topMargin] + [self _headerHeight]*scale];
2582 [info setBottomMargin:[info bottomMargin] + [self _footerHeight]*scale];
2585 - (void)_drawHeaderAndFooter
2587 // The header and footer rect height scales with the page, but the width is always
2588 // all the way across the printed page (inset by printing margins).
2589 NSPrintOperation *op = [NSPrintOperation currentOperation];
2590 float scale = [op _web_pageSetupScaleFactor];
2591 NSPrintInfo *printInfo = [op printInfo];
2592 NSSize paperSize = [printInfo paperSize];
2593 float headerFooterLeft = [printInfo leftMargin]/scale;
2594 float headerFooterWidth = (paperSize.width - ([printInfo leftMargin] + [printInfo rightMargin]))/scale;
2595 NSRect footerRect = NSMakeRect(headerFooterLeft, [printInfo bottomMargin]/scale - [self _footerHeight] ,
2596 headerFooterWidth, [self _footerHeight]);
2597 NSRect headerRect = NSMakeRect(headerFooterLeft, (paperSize.height - [printInfo topMargin])/scale,
2598 headerFooterWidth, [self _headerHeight]);
2600 [self _drawHeaderInRect:headerRect];
2601 [self _drawFooterInRect:footerRect];
2605 @implementation WebView (WebDebugBinding)
2607 - (void)addObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context
2609 LOG (Bindings, "addObserver:%p forKeyPath:%@ options:%x context:%p", anObserver, keyPath, options, context);
2610 [super addObserver:anObserver forKeyPath:keyPath options:options context:context];
2613 - (void)removeObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath
2615 LOG (Bindings, "removeObserver:%p forKeyPath:%@", anObserver, keyPath);
2616 [super removeObserver:anObserver forKeyPath:keyPath];
2621 //==========================================================================================
2624 @implementation WebView (WebViewCSS)
2626 - (DOMCSSStyleDeclaration *)computedStyleForElement:(DOMElement *)element pseudoElement:(NSString *)pseudoElement
2628 // FIXME: is this the best level for this conversion?
2629 if (pseudoElement == nil) {
2630 pseudoElement = @"";
2632 return [[element ownerDocument] getComputedStyle:element :pseudoElement];
2637 @implementation WebView (WebInternal)
2639 // Return the frame holding first responder
2640 - (WebFrame *)_frameForCurrentSelection
2642 // Find the frame holding the first responder, or holding the first form in the doc
2643 NSResponder *resp = [[self window] firstResponder];
2644 if (!resp || ![resp isKindOfClass:[NSView class]] || ![(NSView *)resp isDescendantOf:self]) {
2645 return [self mainFrame]; // first responder outside our view tree
2647 WebFrameView *frameView = (WebFrameView *)[(NSView *)resp _web_superviewOfClass:[WebFrameView class]];
2648 return [frameView webFrame];
2652 - (WebBridge *)_bridgeForCurrentSelection
2654 return [[self _frameForCurrentSelection] _bridge];
2659 WebFrame *mainFrame = [self mainFrame];
2660 return [[mainFrame dataSource] isLoading]
2661 || [[mainFrame provisionalDataSource] isLoading];
2664 - (WebFrameView *)_frameViewAtWindowPoint:(NSPoint)point
2666 NSView *view = [self hitTest:[[self superview] convertPoint:point toView:nil]];
2667 return (WebFrameView *)[view _web_superviewOfClass:[WebFrameView class] stoppingAtClass:[self class]];
2670 - (WebBridge *)_bridgeAtPoint:(NSPoint)point
2672 return [[[self _frameViewAtWindowPoint:[self convertPoint:point toView:nil]] webFrame] _bridge];
2677 @implementation WebView (WebViewEditing)
2679 - (DOMRange *)editableDOMRangeForPoint:(NSPoint)point
2681 WebBridge *bridge = [self _bridgeAtPoint:point];
2682 return [bridge editableDOMRangeForPoint:[self convertPoint:point toView:[[[bridge webFrame] frameView] documentView]]];
2685 - (BOOL)_shouldBeginEditingInDOMRange:(DOMRange *)range
2687 return [[self _editingDelegateForwarder] webView:self shouldBeginEditingInDOMRange:range];
2690 - (BOOL)_shouldEndEditingInDOMRange:(DOMRange *)range
2692 return [[self _editingDelegateForwarder] webView:self shouldEndEditingInDOMRange:range];
2697 id documentView = [[[self mainFrame] frameView] documentView];
2698 return [documentView respondsToSelector:@selector(_canPaste)] && [documentView _canPaste];
2701 - (void)setSelectedDOMRange:(DOMRange *)range affinity:(NSSelectionAffinity)selectionAffinity
2703 // Derive the bridge to use from the range passed in.
2704 // Using _bridgeForCurrentSelection could give us a different document than
2705 // the one the range uses.
2706 [[[range startContainer] _bridge] setSelectedDOMRange:range affinity:selectionAffinity closeTyping:YES];
2709 - (DOMRange *)selectedDOMRange
2711 return [[self _bridgeForCurrentSelection] selectedDOMRange];
2714 - (NSSelectionAffinity)selectionAffinity
2716 return [[self _bridgeForCurrentSelection] selectionAffinity];
2719 - (void)setEditable:(BOOL)flag
2721 if (_private->editable != flag) {
2722 _private->editable = flag;
2723 WebBridge *bridge = [[self mainFrame] _bridge];
2725 [bridge applyEditingStyleToBodyElement];
2726 // If the WebView is made editable and the selection is empty, set it to something.
2727 if ([self selectedDOMRange] == nil)
2728 [bridge setSelectionFromNone];
2731 [bridge removeEditingStyleFromBodyElement];
2738 return _private->editable;
2741 - (void)setTypingStyle:(DOMCSSStyleDeclaration *)style
2743 // We don't know enough at thls level to pass in a relevant WebUndoAction; we'd have to
2744 // change the API to allow this.
2745 [[self _bridgeForCurrentSelection] setTypingStyle:style withUndoAction:WebUndoActionUnspecified];
2748 - (DOMCSSStyleDeclaration *)typingStyle
2750 return [[self _bridgeForCurrentSelection] typingStyle];
2753 - (void)setSmartInsertDeleteEnabled:(BOOL)flag
2755 _private->smartInsertDeleteEnabled = flag;
2758 - (BOOL)smartInsertDeleteEnabled
2760 return _private->smartInsertDeleteEnabled;
2763 - (void)setContinuousSpellCheckingEnabled:(BOOL)flag
2765 _private->continuousSpellCheckingEnabled = flag;
2766 if ([self isContinuousSpellCheckingEnabled]) {
2767 [self _preflightSpellChecker];
2769 [[self mainFrame] _unmarkAllMisspellings];
2773 - (BOOL)isContinuousSpellCheckingEnabled
2775 return _private->continuousSpellCheckingEnabled && [self _continuousCheckingAllowed];
2778 - (int)spellCheckerDocumentTag
2780 if (!_private->hasSpellCheckerDocumentTag) {
2781 _private->spellCheckerDocumentTag = [NSSpellChecker uniqueSpellDocumentTag];
2782 _private->hasSpellCheckerDocumentTag = YES;
2784 return _private->spellCheckerDocumentTag;
2787 - (NSUndoManager *)undoManager
2789 NSUndoManager *undoManager = [[self _editingDelegateForwarder] undoManagerForWebView:self];
2793 return [super undoManager];
2796 - (void)registerForEditingDelegateNotification:(NSString *)name selector:(SEL)selector
2798 NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
2799 if ([_private->editingDelegate respondsToSelector:selector])
2800 [defaultCenter addObserver:_private->editingDelegate selector:selector name:name object:self];
2803 - (void)setEditingDelegate:(id)delegate
2805 if (_private->editingDelegate == delegate)
2808 NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
2810 // remove notifications from current delegate
2811 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidBeginEditingNotification object:self];
2812 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidChangeNotification object:self];
2813 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidEndEditingNotification object:self];
2814 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidChangeTypingStyleNotification object:self];
2815 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidChangeSelectionNotification object:self];
2817 _private->editingDelegate = delegate;
2818 [_private->editingDelegateForwarder release];
2819 _private->editingDelegateForwarder = nil;
2821 // add notifications for new delegate
2822 [self registerForEditingDelegateNotification:WebViewDidBeginEditingNotification selector:@selector(webViewDidBeginEditing:)];
2823 [self registerForEditingDelegateNotification:WebViewDidChangeNotification selector:@selector(webViewDidChange:)];
2824 [self registerForEditingDelegateNotification:WebViewDidEndEditingNotification selector:@selector(webViewDidEndEditing:)];
2825 [self registerForEditingDelegateNotification:WebViewDidChangeTypingStyleNotification selector:@selector(webViewDidChangeTypingStyle:)];
2826 [self registerForEditingDelegateNotification:WebViewDidChangeSelectionNotification selector:@selector(webViewDidChangeSelection:)];
2829 - (id)editingDelegate
2831 return _private->editingDelegate;
2834 - (DOMCSSStyleDeclaration *)styleDeclarationWithText:(NSString *)text
2836 // FIXME: Should this really be attached to the document with the current selection?
2837 DOMCSSStyleDeclaration *decl = [[[self _bridgeForCurrentSelection] DOMDocument] createCSSStyleDeclaration];
2838 [decl setCssText:text];
2844 @implementation WebView (WebViewUndoableEditing)
2846 - (void)replaceSelectionWithNode:(DOMNode *)node
2848 [[self _bridgeForCurrentSelection] replaceSelectionWithNode:node selectReplacement:YES smartReplace:NO];
2851 - (void)replaceSelectionWithText:(NSString *)text
2853 [[self _bridgeForCurrentSelection] replaceSelectionWithText:text selectReplacement:YES smartReplace:NO];
2856 - (void)replaceSelectionWithMarkupString:(NSString *)markupString
2858 [[self _bridgeForCurrentSelection] replaceSelectionWithMarkupString:markupString baseURLString:nil selectReplacement:YES smartReplace:NO];
2861 - (void)replaceSelectionWithArchive:(WebArchive *)archive
2863 [[[[self _bridgeForCurrentSelection] webFrame] dataSource] _replaceSelectionWithArchive:archive selectReplacement:YES];
2866 - (void)deleteSelection
2868 WebBridge *bridge = [self _bridgeForCurrentSelection];
2869 [bridge deleteSelectionWithSmartDelete:[(WebHTMLView *)[[[bridge webFrame] frameView] documentView] _canSmartCopyOrDelete]];
2872 - (void)applyStyle:(DOMCSSStyleDeclaration *)style
2874 // We don't know enough at thls level to pass in a relevant WebUndoAction; we'd have to
2875 // change the API to allow this.
2876 [[self _bridgeForCurrentSelection] applyStyle:style withUndoAction:WebUndoActionUnspecified];
2881 @implementation WebView (WebViewEditingActions)
2883 - (void)_performResponderOperation:(SEL)selector with:(id)parameter
2885 static BOOL reentered = NO;
2887 [[self nextResponder] tryToPerform:selector with:parameter];
2891 // There are two possibilities here.
2893 // One is that WebView has been called in its role as part of the responder chain.
2894 // In that case, it's fine to call the first responder and end up calling down the
2895 // responder chain again. Later we will return here with reentered = YES and continue
2896 // past the WebView.
2898 // The other is that we are being called directly, in which case we want to pass the
2899 // selector down to the view inside us that can handle it, and continue down the
2900 // responder chain as usual.
2902 // Pass this selector down to the first responder.
2903 NSResponder *responder = [self _responderForResponderOperations];
2905 [responder tryToPerform:selector with:parameter];
2909 #define FORWARD(name) \
2910 - (void)name:(id)sender { [self _performResponderOperation:_cmd with:sender]; }
2912 FOR_EACH_RESPONDER_SELECTOR(FORWARD)
2914 - (void)insertText:(NSString *)text
2916 [self _performResponderOperation:_cmd with:text];
2921 @implementation WebView (WebViewEditingInMail)
2923 - (void)_insertNewlineInQuotedContent;
2925 [[self _bridgeForCurrentSelection] insertParagraphSeparatorInQuotedContent];
2928 - (BOOL)_selectWordBeforeMenuEvent
2930 return _private->selectWordBeforeMenuEvent;
2933 - (void)_setSelectWordBeforeMenuEvent:(BOOL)flag
2935 _private->selectWordBeforeMenuEvent = flag;
2940 @implementation WebView (WebFileInternal)
2942 - (void)_preflightSpellCheckerNow:(id)sender
2944 [[NSSpellChecker sharedSpellChecker] _preflightChosenSpellServer];
2947 - (void)_preflightSpellChecker
2949 // As AppKit does, we wish to delay tickling the shared spellchecker into existence on application launch.
2950 if ([NSSpellChecker sharedSpellCheckerExists]) {
2951 [self _preflightSpellCheckerNow:self];
2953 [self performSelector:@selector(_preflightSpellCheckerNow:) withObject:self afterDelay:2.0];
2957 - (BOOL)_continuousCheckingAllowed
2959 static BOOL allowContinuousSpellChecking = YES;
2960 static BOOL readAllowContinuousSpellCheckingDefault = NO;
2961 if (!readAllowContinuousSpellCheckingDefault) {
2962 if ([[NSUserDefaults standardUserDefaults] objectForKey:@"NSAllowContinuousSpellChecking"]) {
2963 allowContinuousSpellChecking = [[NSUserDefaults standardUserDefaults] boolForKey:@"NSAllowContinuousSpellChecking"];
2965 readAllowContinuousSpellCheckingDefault = YES;
2967 return allowContinuousSpellChecking;
2970 - (NSResponder *)_responderForResponderOperations
2972 NSResponder *responder = [[self window] firstResponder];
2973 if (![self _web_firstResponderIsSelfOrDescendantView]) {
2974 responder = [[[self mainFrame] frameView] documentView];
2976 responder = [[self mainFrame] frameView];