2 * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
3 * Copyright (C) 2006 David Smith (catfish.man@gmail.com)
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15 * its contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #import "WebViewInternal.h"
32 #import "DOMRangeInternal.h"
33 #import "WebBackForwardList.h"
34 #import "WebBackForwardListInternal.h"
35 #import "WebBaseNetscapePluginView.h"
36 #import "WebChromeClient.h"
37 #import "WebContextMenuClient.h"
38 #import "WebDOMOperationsPrivate.h"
39 #import "WebDashboardRegion.h"
40 #import "WebDatabaseManagerInternal.h"
41 #import "WebDatabaseManagerPrivate.h"
42 #import "WebDataSourceInternal.h"
43 #import "WebDefaultEditingDelegate.h"
44 #import "WebDefaultPolicyDelegate.h"
45 #import "WebDefaultScriptDebugDelegate.h"
46 #import "WebDefaultUIDelegate.h"
47 #import "WebDocument.h"
48 #import "WebDocumentInternal.h"
49 #import "WebDownload.h"
50 #import "WebDownloadInternal.h"
51 #import "WebDragClient.h"
52 #import "WebDynamicScrollBarsView.h"
53 #import "WebEditingDelegate.h"
54 #import "WebEditorClient.h"
55 #import "WebFormDelegatePrivate.h"
56 #import "WebFrameBridge.h"
57 #import "WebFrameInternal.h"
58 #import "WebFrameViewInternal.h"
59 #import "WebHTMLRepresentation.h"
60 #import "WebHTMLViewInternal.h"
61 #import "WebHistoryItemInternal.h"
62 #import "WebIconDatabase.h"
63 #import "WebIconDatabaseInternal.h"
64 #import "WebInspector.h"
65 #import "WebInspectorClient.h"
66 #import "WebKitErrors.h"
67 #import "WebKitLogging.h"
68 #import "WebKitNSStringExtras.h"
69 #import "WebKitStatisticsPrivate.h"
70 #import "WebKitSystemBits.h"
71 #import "WebKitVersionChecks.h"
72 #import "WebLocalizableStrings.h"
73 #import "WebNSDataExtras.h"
74 #import "WebNSDataExtrasPrivate.h"
75 #import "WebNSDictionaryExtras.h"
76 #import "WebNSEventExtras.h"
77 #import "WebNSObjectExtras.h"
78 #import "WebNSPasteboardExtras.h"
79 #import "WebNSPrintOperationExtras.h"
80 #import "WebNSURLExtras.h"
81 #import "WebNSURLRequestExtras.h"
82 #import "WebNSUserDefaultsExtras.h"
83 #import "WebNSViewExtras.h"
84 #import "WebPanelAuthenticationHandler.h"
85 #import "WebPasteboardHelper.h"
86 #import "WebPDFView.h"
87 #import "WebPluginDatabase.h"
88 #import "WebPolicyDelegate.h"
89 #import "WebPreferenceKeysPrivate.h"
90 #import "WebPreferencesPrivate.h"
91 #import "WebScriptDebugDelegatePrivate.h"
92 #import "WebScriptDebugServerPrivate.h"
93 #import "WebUIDelegate.h"
94 #import "WebUIDelegatePrivate.h"
95 #import <CoreFoundation/CFSet.h>
96 #import <Foundation/NSURLConnection.h>
97 #import <JavaScriptCore/Assertions.h>
98 #import <WebCore/Cache.h>
99 #import <WebCore/ColorMac.h>
100 #import <WebCore/Document.h>
101 #import <WebCore/DocumentLoader.h>
102 #import <WebCore/DragController.h>
103 #import <WebCore/DragData.h>
104 #import <WebCore/Editor.h>
105 #import <WebCore/ExceptionHandlers.h>
106 #import <WebCore/Frame.h>
107 #import <WebCore/FrameLoader.h>
108 #import <WebCore/FrameTree.h>
109 #import <WebCore/HTMLNames.h>
110 #import <WebCore/HistoryItem.h>
111 #import <WebCore/Logging.h>
112 #import <WebCore/MIMETypeRegistry.h>
113 #import <WebCore/Page.h>
114 #import <WebCore/PageCache.h>
115 #import <WebCore/PlatformMouseEvent.h>
116 #import <WebCore/ProgressTracker.h>
117 #import <WebCore/SelectionController.h>
118 #import <WebCore/Settings.h>
119 #import <WebCore/TextResourceDecoder.h>
120 #import <WebCore/WebCoreFrameBridge.h>
121 #import <WebCore/WebCoreObjCExtras.h>
122 #import <WebCore/WebCoreTextRenderer.h>
123 #import <WebCore/WebCoreView.h>
124 #import <WebKit/DOM.h>
125 #import <WebKit/DOMExtensions.h>
126 #import <WebKit/DOMPrivate.h>
127 #import <WebKitSystemInterface.h>
128 #import <mach-o/dyld.h>
129 #import <objc/objc-runtime.h>
130 #import <wtf/RefPtr.h>
131 #import <wtf/HashTraits.h>
133 using namespace WebCore;
135 #if defined(__ppc__) || defined(__ppc64__)
136 #define PROCESSOR "PPC"
137 #elif defined(__i386__) || defined(__x86_64__)
138 #define PROCESSOR "Intel"
140 #error Unknown architecture
143 #define FOR_EACH_RESPONDER_SELECTOR(macro) \
145 macro(alignJustified) \
148 macro(capitalizeWord) \
149 macro(centerSelectionInVisibleArea) \
150 macro(changeAttributes) \
152 macro(changeDocumentBackgroundColor) \
154 macro(checkSpelling) \
160 macro(deleteBackward) \
161 macro(deleteBackwardByDecomposingPreviousCharacter) \
162 macro(deleteForward) \
163 macro(deleteToBeginningOfLine) \
164 macro(deleteToBeginningOfParagraph) \
165 macro(deleteToEndOfLine) \
166 macro(deleteToEndOfParagraph) \
167 macro(deleteWordBackward) \
168 macro(deleteWordForward) \
169 macro(ignoreSpelling) \
171 macro(insertBacktab) \
172 macro(insertNewline) \
173 macro(insertNewlineIgnoringFieldEditor) \
174 macro(insertParagraphSeparator) \
176 macro(insertTabIgnoringFieldEditor) \
177 macro(lowercaseWord) \
178 macro(moveBackward) \
179 macro(moveBackwardAndModifySelection) \
181 macro(moveDownAndModifySelection) \
183 macro(moveForwardAndModifySelection) \
185 macro(moveLeftAndModifySelection) \
187 macro(moveRightAndModifySelection) \
188 macro(moveToBeginningOfDocument) \
189 macro(moveToBeginningOfDocumentAndModifySelection) \
190 macro(moveToBeginningOfSentence) \
191 macro(moveToBeginningOfSentenceAndModifySelection) \
192 macro(moveToBeginningOfLine) \
193 macro(moveToBeginningOfLineAndModifySelection) \
194 macro(moveToBeginningOfParagraph) \
195 macro(moveToBeginningOfParagraphAndModifySelection) \
196 macro(moveToEndOfDocument) \
197 macro(moveToEndOfDocumentAndModifySelection) \
198 macro(moveToEndOfLine) \
199 macro(moveToEndOfLineAndModifySelection) \
200 macro(moveToEndOfParagraph) \
201 macro(moveToEndOfParagraphAndModifySelection) \
202 macro(moveToEndOfSentence) \
203 macro(moveToEndOfSentenceAndModifySelection) \
205 macro(moveUpAndModifySelection) \
206 macro(moveWordBackward) \
207 macro(moveWordBackwardAndModifySelection) \
208 macro(moveWordForward) \
209 macro(moveWordForwardAndModifySelection) \
210 macro(moveWordLeft) \
211 macro(moveWordLeftAndModifySelection) \
212 macro(moveWordRight) \
213 macro(moveWordRightAndModifySelection) \
218 macro(pasteAsPlainText) \
219 macro(pasteAsRichText) \
221 macro(performFindPanelAction) \
222 macro(scrollLineDown) \
223 macro(scrollLineUp) \
224 macro(scrollPageDown) \
225 macro(scrollPageUp) \
226 macro(scrollToBeginningOfDocument) \
227 macro(scrollToEndOfDocument) \
230 macro(selectSentence) \
232 macro(selectParagraph) \
233 macro(showGuessPanel) \
234 macro(startSpeaking) \
235 macro(stopSpeaking) \
240 macro(uppercaseWord) \
242 macro(yankAndSelect) \
244 #define WebKitOriginalTopPrintingMarginKey @"WebKitOriginalTopMargin"
245 #define WebKitOriginalBottomPrintingMarginKey @"WebKitOriginalBottomMargin"
247 static BOOL s_didSetCacheModel;
248 static WebCacheModel s_cacheModel = WebCacheModelDocumentViewer;
250 static BOOL applicationIsTerminating;
251 static int pluginDatabaseClientCount = 0;
253 @interface NSSpellChecker (AppKitSecretsIKnow)
254 - (void)_preflightChosenSpellServer;
257 @interface NSView (AppKitSecretsIKnow)
258 - (NSView *)_hitTest:(NSPoint *)aPoint dragTypes:(NSSet *)types;
259 - (void)_autoscrollForDraggingInfo:(id)dragInfo timeDelta:(NSTimeInterval)repeatDelta;
260 - (BOOL)_shouldAutoscrollForDraggingInfo:(id)dragInfo;
263 @interface NSWindow (AppKitSecretsIKnow)
264 - (id)_oldFirstResponderBeforeBecoming;
267 @interface NSObject (ValidateWithoutDelegate)
268 - (BOOL)validateUserInterfaceItemWithoutDelegate:(id <NSValidatedUserInterfaceItem>)item;
271 @interface _WebSafeForwarder : NSObject
273 id target; // Non-retained. Don't retain delegates.
275 BOOL catchExceptions;
277 - (id)initWithTarget:(id)target defaultTarget:(id)defaultTarget catchExceptions:(BOOL)catchExceptions;
280 @interface WebViewPrivate : NSObject
286 id UIDelegateForwarder;
287 id resourceProgressDelegate;
290 id policyDelegateForwarder;
291 id frameLoadDelegate;
292 id frameLoadDelegateForwarder;
293 id <WebFormDelegate> formDelegate;
295 id editingDelegateForwarder;
296 id scriptDebugDelegate;
297 id scriptDebugDelegateForwarder;
299 WebInspector *inspector;
303 float textSizeMultiplier;
305 NSString *applicationNameForUserAgent;
307 BOOL userAgentOverridden;
309 WebPreferences *preferences;
310 BOOL useSiteSpecificSpoofing;
312 NSWindow *hostWindow;
314 int programmaticFocusCount;
316 WebResourceDelegateImplementationCache resourceLoadDelegateImplementations;
317 WebFrameLoadDelegateImplementationCache frameLoadDelegateImplementations;
319 void *observationInfo;
322 BOOL shouldCloseWithWindow;
323 BOOL mainFrameDocumentReady;
324 BOOL drawsBackground;
326 BOOL tabKeyCyclesThroughElementsChanged;
327 BOOL becomingFirstResponder;
328 BOOL becomingFirstResponderFromOutside;
329 BOOL hoverFeedbackSuspended;
331 BOOL catchesDelegateExceptions;
333 NSColor *backgroundColor;
335 NSString *mediaStyle;
337 BOOL hasSpellCheckerDocumentTag;
338 NSInteger spellCheckerDocumentTag;
340 BOOL smartInsertDeleteEnabled;
342 BOOL dashboardBehaviorAlwaysSendMouseEventsToAllWindows;
343 BOOL dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns;
344 BOOL dashboardBehaviorAlwaysAcceptsFirstMouse;
345 BOOL dashboardBehaviorAllowWheelScrolling;
347 // WebKit has both a global plug-in database and a separate, per WebView plug-in database. Dashboard uses the per WebView database.
348 WebPluginDatabase *pluginDatabase;
350 HashMap<unsigned long, RetainPtr<id> >* identifierMap;
354 @interface WebView (WebFileInternal)
355 + (void)_setCacheModel:(WebCacheModel)cacheModel;
356 + (WebCacheModel)_cacheModel;
357 - (WebFrame *)_selectedOrMainFrame;
358 - (WebFrameBridge *)_bridgeForSelectedOrMainFrame;
360 - (WebFrameView *)_frameViewAtWindowPoint:(NSPoint)point;
361 - (WebFrame *)_focusedFrame;
362 + (void)_preflightSpellChecker;
363 - (BOOL)_continuousCheckingAllowed;
364 - (NSResponder *)_responderForResponderOperations;
365 - (BOOL)_performTextSizingSelector:(SEL)sel withObject:(id)arg onTrackingDocs:(BOOL)doTrackingViews selForNonTrackingDocs:(SEL)testSel newScaleFactor:(float)newScaleFactor;
366 - (void)_notifyTextSizeMultiplierChanged;
369 @interface WebView (WebCallDelegateFunctions)
372 NSString *WebElementDOMNodeKey = @"WebElementDOMNode";
373 NSString *WebElementFrameKey = @"WebElementFrame";
374 NSString *WebElementImageKey = @"WebElementImage";
375 NSString *WebElementImageAltStringKey = @"WebElementImageAltString";
376 NSString *WebElementImageRectKey = @"WebElementImageRect";
377 NSString *WebElementImageURLKey = @"WebElementImageURL";
378 NSString *WebElementIsSelectedKey = @"WebElementIsSelected";
379 NSString *WebElementLinkLabelKey = @"WebElementLinkLabel";
380 NSString *WebElementLinkTargetFrameKey = @"WebElementTargetFrame";
381 NSString *WebElementLinkTitleKey = @"WebElementLinkTitle";
382 NSString *WebElementLinkURLKey = @"WebElementLinkURL";
383 NSString *WebElementSpellingToolTipKey = @"WebElementSpellingToolTip";
384 NSString *WebElementTitleKey = @"WebElementTitle";
385 NSString *WebElementLinkIsLiveKey = @"WebElementLinkIsLive";
386 NSString *WebElementIsContentEditableKey = @"WebElementIsContentEditableKey";
388 NSString *WebViewProgressStartedNotification = @"WebProgressStartedNotification";
389 NSString *WebViewProgressEstimateChangedNotification = @"WebProgressEstimateChangedNotification";
390 NSString *WebViewProgressFinishedNotification = @"WebProgressFinishedNotification";
392 NSString * const WebViewDidBeginEditingNotification = @"WebViewDidBeginEditingNotification";
393 NSString * const WebViewDidChangeNotification = @"WebViewDidChangeNotification";
394 NSString * const WebViewDidEndEditingNotification = @"WebViewDidEndEditingNotification";
395 NSString * const WebViewDidChangeTypingStyleNotification = @"WebViewDidChangeTypingStyleNotification";
396 NSString * const WebViewDidChangeSelectionNotification = @"WebViewDidChangeSelectionNotification";
398 enum { WebViewVersion = 4 };
400 #define timedLayoutSize 4096
402 static NSMutableSet *schemesWithRepresentationsSet;
404 NSString *_WebCanGoBackKey = @"canGoBack";
405 NSString *_WebCanGoForwardKey = @"canGoForward";
406 NSString *_WebEstimatedProgressKey = @"estimatedProgress";
407 NSString *_WebIsLoadingKey = @"isLoading";
408 NSString *_WebMainFrameIconKey = @"mainFrameIcon";
409 NSString *_WebMainFrameTitleKey = @"mainFrameTitle";
410 NSString *_WebMainFrameURLKey = @"mainFrameURL";
411 NSString *_WebMainFrameDocumentKey = @"mainFrameDocument";
413 @interface WebProgressItem : NSObject
416 long long bytesReceived;
417 long long estimatedLength;
421 @implementation WebProgressItem
424 static BOOL continuousSpellCheckingEnabled;
425 #ifndef BUILDING_ON_TIGER
426 static BOOL grammarCheckingEnabled;
429 @implementation WebViewPrivate
431 #ifndef BUILDING_ON_TIGER
434 WebCoreObjCFinalizeOnMainThread(self);
444 textSizeMultiplier = 1;
445 dashboardBehaviorAllowWheelScrolling = YES;
446 shouldCloseWithWindow = objc_collecting_enabled();
447 continuousSpellCheckingEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebContinuousSpellCheckingEnabled];
449 #ifndef BUILDING_ON_TIGER
450 grammarCheckingEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebGrammarCheckingEnabled];
452 userAgent = new String;
456 identifierMap = new HashMap<unsigned long, RetainPtr<id> >();
457 pluginDatabaseClientCount++;
465 ASSERT(!preferences);
468 delete identifierMap;
470 [applicationNameForUserAgent release];
471 [backgroundColor release];
474 [hostWindow release];
476 [policyDelegateForwarder release];
477 [UIDelegateForwarder release];
478 [frameLoadDelegateForwarder release];
479 [editingDelegateForwarder release];
480 [scriptDebugDelegateForwarder release];
482 [mediaStyle release];
489 ASSERT_MAIN_THREAD();
492 delete identifierMap;
499 @implementation WebView (AllWebViews)
501 static CFSetCallBacks NonRetainingSetCallbacks = {
510 static CFMutableSetRef allWebViewsSet;
512 + (void)_makeAllWebViewsPerformSelector:(SEL)selector
517 [(NSMutableSet *)allWebViewsSet makeObjectsPerformSelector:selector];
520 - (void)_removeFromAllWebViewsSet
523 CFSetRemoveValue(allWebViewsSet, self);
526 - (void)_addToAllWebViewsSet
529 allWebViewsSet = CFSetCreateMutable(NULL, 0, &NonRetainingSetCallbacks);
531 CFSetSetValue(allWebViewsSet, self);
536 @implementation WebView (WebPrivate)
538 #ifdef DEBUG_WIDGET_DRAWING
539 static bool debugWidget = true;
540 - (void)drawRect:(NSRect)rect
542 [[NSColor blueColor] set];
545 NSRect htmlViewRect = [[[[self mainFrame] frameView] documentView] frame];
548 while (debugWidget) {
553 NSLog (@"%s: rect: (%0.f,%0.f) %0.f %0.f, htmlViewRect: (%0.f,%0.f) %0.f %0.f\n",
554 __PRETTY_FUNCTION__, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height,
555 htmlViewRect.origin.x, htmlViewRect.origin.y, htmlViewRect.size.width, htmlViewRect.size.height
558 [super drawRect:rect];
562 + (BOOL)_scriptDebuggerEnabled
565 return [[NSUserDefaults standardUserDefaults] boolForKey:@"WebKitScriptDebuggerEnabled"];
567 return YES; // always enable in debug builds
571 + (NSArray *)_supportedMIMETypes
573 // Load the plug-in DB allowing plug-ins to install types.
574 [WebPluginDatabase sharedDatabase];
575 return [[WebFrameView _viewTypesAllowImageTypeOmission:NO] allKeys];
578 + (NSArray *)_supportedFileExtensions
580 NSMutableSet *extensions = [[NSMutableSet alloc] init];
581 NSArray *MIMETypes = [self _supportedMIMETypes];
582 NSEnumerator *enumerator = [MIMETypes objectEnumerator];
584 while ((MIMEType = [enumerator nextObject]) != nil) {
585 NSArray *extensionsForType = WKGetExtensionsForMIMEType(MIMEType);
586 if (extensionsForType) {
587 [extensions addObjectsFromArray:extensionsForType];
590 NSArray *uniqueExtensions = [extensions allObjects];
591 [extensions release];
592 return uniqueExtensions;
595 + (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType;
597 MIMEType = [MIMEType lowercaseString];
598 Class viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:YES] _webkit_objectForMIMEType:MIMEType];
599 Class repClass = [[WebDataSource _repTypesAllowImageTypeOmission:YES] _webkit_objectForMIMEType:MIMEType];
601 if (!viewClass || !repClass || [[WebPDFView supportedMIMETypes] containsObject:MIMEType]) {
602 // Our optimization to avoid loading the plug-in DB and image types for the HTML case failed.
603 // Load the plug-in DB allowing plug-ins to install types.
604 [WebPluginDatabase sharedDatabase];
606 // Load the image types and get the view class and rep class. This should be the fullest picture of all handled types.
607 viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:NO] _webkit_objectForMIMEType:MIMEType];
608 repClass = [[WebDataSource _repTypesAllowImageTypeOmission:NO] _webkit_objectForMIMEType:MIMEType];
611 if (viewClass && repClass) {
612 // Special-case WebHTMLView for text types that shouldn't be shown.
613 if (viewClass == [WebHTMLView class] &&
614 repClass == [WebHTMLRepresentation class] &&
615 [[WebHTMLView unsupportedTextMIMETypes] containsObject:MIMEType]) {
628 - (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType;
630 if ([[self class] _viewClass:vClass andRepresentationClass:rClass forMIMEType:MIMEType])
633 if (_private->pluginDatabase) {
634 WebBasePluginPackage *pluginPackage = [_private->pluginDatabase pluginForMIMEType:MIMEType];
637 *vClass = [WebHTMLView class];
639 *rClass = [WebHTMLRepresentation class];
647 + (void)_setAlwaysUseATSU:(BOOL)f
649 WebCoreSetAlwaysUseATSU(f);
652 + (BOOL)canShowFile:(NSString *)path
654 return [[self class] canShowMIMEType:[WebView _MIMETypeForFile:path]];
657 + (NSString *)suggestedFileExtensionForMIMEType:(NSString *)type
659 return WKGetPreferredExtensionForMIMEType(type);
664 if (!_private || _private->closed)
671 if (!_private || _private->closed)
674 FrameLoader* mainFrameLoader = [[self mainFrame] _frameLoader];
676 mainFrameLoader->detachFromParent();
678 [self _removeFromAllWebViewsSet];
679 [self setGroupName:nil];
680 [self setHostWindow:nil];
682 [self setDownloadDelegate:nil];
683 [self setEditingDelegate:nil];
684 [self setFrameLoadDelegate:nil];
685 [self setPolicyDelegate:nil];
686 [self setResourceLoadDelegate:nil];
687 [self setScriptDebugDelegate:nil];
688 [self setUIDelegate:nil];
690 [_private->inspector webViewClosed];
692 // setHostWindow:nil must be called before this value is set (see 5408186)
693 _private->closed = YES;
695 // To avoid leaks, call removeDragCaret in case it wasn't called after moveDragCaretToPoint.
696 [self removeDragCaret];
698 // Deleteing the WebCore::Page will clear the page cache so we call destroy on
699 // all the plug-ins in the page cache to break any retain cycles.
700 // See comment in HistoryItem::releaseAllPendingPageCaches() for more information.
701 delete _private->page;
704 if (_private->hasSpellCheckerDocumentTag) {
705 [[NSSpellChecker sharedSpellChecker] closeSpellDocumentWithTag:_private->spellCheckerDocumentTag];
706 _private->hasSpellCheckerDocumentTag = NO;
709 [[NSNotificationCenter defaultCenter] removeObserver:self];
711 [WebPreferences _removeReferenceForIdentifier:[self preferencesIdentifier]];
713 WebPreferences *preferences = _private->preferences;
714 _private->preferences = nil;
715 [preferences didRemoveFromWebView];
716 [preferences release];
718 pluginDatabaseClientCount--;
720 // Make sure to close both sets of plug-ins databases because plug-ins need an opportunity to clean up files, etc.
722 // Unload the WebView local plug-in database.
723 if (_private->pluginDatabase) {
724 [_private->pluginDatabase close];
725 [_private->pluginDatabase release];
726 _private->pluginDatabase = nil;
729 // Keep the global plug-in database active until the app terminates to avoid having to reload plug-in bundles.
730 if (!pluginDatabaseClientCount && applicationIsTerminating)
731 [WebPluginDatabase closeSharedDatabase];
734 + (NSString *)_MIMETypeForFile:(NSString *)path
736 NSString *extension = [path pathExtension];
737 NSString *MIMEType = nil;
739 // Get the MIME type from the extension.
740 if ([extension length] != 0) {
741 MIMEType = WKGetMIMETypeForExtension(extension);
744 // If we can't get a known MIME type from the extension, sniff.
745 if ([MIMEType length] == 0 || [MIMEType isEqualToString:@"application/octet-stream"]) {
746 NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:path];
747 NSData *data = [handle readDataOfLength:WEB_GUESS_MIME_TYPE_PEEK_LENGTH];
749 if ([data length] != 0) {
750 MIMEType = [data _webkit_guessedMIMEType];
752 if ([MIMEType length] == 0) {
753 MIMEType = @"application/octet-stream";
760 - (WebDownload *)_downloadURL:(NSURL *)URL
764 NSURLRequest *request = [[NSURLRequest alloc] initWithURL:URL];
765 WebDownload *download = [WebDownload _downloadWithRequest:request
766 delegate:_private->downloadDelegate
773 - (WebView *)_openNewWindowWithRequest:(NSURLRequest *)request
775 NSDictionary *features = [[NSDictionary alloc] init];
776 WebView *newWindowWebView = [[self _UIDelegateForwarder] webView:self
777 createWebViewWithRequest:nil
778 windowFeatures:features];
780 if (!newWindowWebView)
783 CallUIDelegate(newWindowWebView, @selector(webViewShow:));
784 return newWindowWebView;
787 - (WebInspector *)inspector
789 if (!_private->inspector)
790 _private->inspector = [[WebInspector alloc] initWithWebView:self];
791 return _private->inspector;
794 - (WebCore::Page*)page
796 return _private->page;
799 - (NSMenu *)_menuForElement:(NSDictionary *)element defaultItems:(NSArray *)items
801 NSArray *defaultMenuItems = [[WebDefaultUIDelegate sharedUIDelegate] webView:self contextMenuItemsForElement:element defaultMenuItems:items];
803 NSArray *menuItems = CallUIDelegate(self, @selector(webView:contextMenuItemsForElement:defaultMenuItems:), element, defaultMenuItems);
807 unsigned count = [menuItems count];
811 NSMenu *menu = [[NSMenu alloc] init];
812 for (unsigned i = 0; i < count; i++)
813 [menu addItem:[menuItems objectAtIndex:i]];
815 return [menu autorelease];
818 - (void)_mouseDidMoveOverElement:(NSDictionary *)dictionary modifierFlags:(NSUInteger)modifierFlags
820 // We originally intended to call this delegate method sometimes with a nil dictionary, but due to
821 // a bug dating back to WebKit 1.0 this delegate was never called with nil! Unfortunately we can't
822 // start calling this with nil since it will break Adobe Help Viewer, and possibly other clients.
825 CallUIDelegate(self, @selector(webView:mouseDidMoveOverElement:modifierFlags:), dictionary, modifierFlags);
828 - (void)_loadBackForwardListFromOtherView:(WebView *)otherView
833 if (!otherView->_private->page)
836 // It turns out the right combination of behavior is done with the back/forward load
837 // type. (See behavior matrix at the top of WebFramePrivate.) So we copy all the items
838 // in the back forward list, and go to the current one.
840 BackForwardList* backForwardList = _private->page->backForwardList();
841 ASSERT(!backForwardList->currentItem()); // destination list should be empty
843 BackForwardList* otherBackForwardList = otherView->_private->page->backForwardList();
844 if (!otherBackForwardList->currentItem())
845 return; // empty back forward list, bail
847 HistoryItem* newItemToGoTo = 0;
849 int lastItemIndex = otherBackForwardList->forwardListCount();
850 for (int i = -otherBackForwardList->backListCount(); i <= lastItemIndex; ++i) {
852 // If this item is showing , save away its current scroll and form state,
853 // since that might have changed since loading and it is normally not saved
854 // until we leave that page.
855 otherView->_private->page->mainFrame()->loader()->saveDocumentAndScrollState();
857 RefPtr<HistoryItem> newItem = otherBackForwardList->itemAtIndex(i)->copy();
859 newItemToGoTo = newItem.get();
860 backForwardList->addItem(newItem.release());
863 ASSERT(newItemToGoTo);
864 _private->page->goToItem(newItemToGoTo, FrameLoadTypeIndexedBackForward);
867 - (void)_setFormDelegate: (id<WebFormDelegate>)delegate
869 _private->formDelegate = delegate;
872 - (id<WebFormDelegate>)_formDelegate
874 return _private->formDelegate;
877 - (BOOL)_needsAdobeFrameReloadingQuirk
879 static BOOL checked = NO;
880 static BOOL needsQuirk = NO;
885 needsQuirk = WKAppVersionCheckLessThan(@"com.adobe.Acrobat", -1, 9.0)
886 || WKAppVersionCheckLessThan(@"com.adobe.Acrobat.Pro", -1, 9.0)
887 || WKAppVersionCheckLessThan(@"com.adobe.Reader", -1, 9.0)
888 || WKAppVersionCheckLessThan(@"com.adobe.distiller", -1, 9.0)
889 || WKAppVersionCheckLessThan(@"com.adobe.Contribute", -1, 4.2)
890 || WKAppVersionCheckLessThan(@"com.adobe.dreamweaver-9.0", -1, 9.1)
891 || WKAppVersionCheckLessThan(@"com.macromedia.fireworks", -1, 9.1)
892 || WKAppVersionCheckLessThan(@"com.adobe.InCopy", -1, 5.1)
893 || WKAppVersionCheckLessThan(@"com.adobe.InDesign", -1, 5.1)
894 || WKAppVersionCheckLessThan(@"com.adobe.Soundbooth", -1, 2);
900 - (BOOL)_needsKeyboardEventDisambiguationQuirks
902 static BOOL checked = NO;
903 static BOOL needsQuirks = NO;
908 needsQuirks = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_IE_COMPATIBLE_KEYBOARD_EVENT_DISPATCH)
909 && ![[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.Safari"];
915 - (void)_preferencesChangedNotification:(NSNotification *)notification
917 WebPreferences *preferences = (WebPreferences *)[notification object];
918 ASSERT(preferences == [self preferences]);
920 if (!_private->userAgentOverridden)
921 *_private->userAgent = String();
923 // Cache this value so we don't have to read NSUserDefaults on each page load
924 _private->useSiteSpecificSpoofing = [preferences _useSiteSpecificSpoofing];
926 // Update corresponding WebCore Settings object.
930 Settings* settings = _private->page->settings();
932 settings->setCursiveFontFamily([preferences cursiveFontFamily]);
933 settings->setDefaultFixedFontSize([preferences defaultFixedFontSize]);
934 settings->setDefaultFontSize([preferences defaultFontSize]);
935 settings->setDefaultTextEncodingName([preferences defaultTextEncodingName]);
936 settings->setFantasyFontFamily([preferences fantasyFontFamily]);
937 settings->setFixedFontFamily([preferences fixedFontFamily]);
938 settings->setForceFTPDirectoryListings([preferences _forceFTPDirectoryListings]);
939 settings->setFTPDirectoryTemplatePath([preferences _ftpDirectoryTemplatePath]);
940 settings->setJavaEnabled([preferences isJavaEnabled]);
941 settings->setJavaScriptEnabled([preferences isJavaScriptEnabled]);
942 settings->setJavaScriptCanOpenWindowsAutomatically([preferences javaScriptCanOpenWindowsAutomatically]);
943 settings->setMinimumFontSize([preferences minimumFontSize]);
944 settings->setMinimumLogicalFontSize([preferences minimumLogicalFontSize]);
945 settings->setPluginsEnabled([preferences arePlugInsEnabled]);
946 settings->setPrivateBrowsingEnabled([preferences privateBrowsingEnabled]);
947 settings->setSansSerifFontFamily([preferences sansSerifFontFamily]);
948 settings->setSerifFontFamily([preferences serifFontFamily]);
949 settings->setStandardFontFamily([preferences standardFontFamily]);
950 settings->setLoadsImagesAutomatically([preferences loadsImagesAutomatically]);
951 settings->setShouldPrintBackgrounds([preferences shouldPrintBackgrounds]);
952 settings->setTextAreasAreResizable([preferences textAreasAreResizable]);
953 settings->setShrinksStandaloneImagesToFit([preferences shrinksStandaloneImagesToFit]);
954 settings->setEditableLinkBehavior(core([preferences editableLinkBehavior]));
955 settings->setDOMPasteAllowed([preferences isDOMPasteAllowed]);
956 settings->setUsesPageCache([self usesPageCache]);
957 settings->setShowsURLsInToolTips([preferences showsURLsInToolTips]);
958 settings->setDeveloperExtrasEnabled([preferences developerExtrasEnabled]);
959 settings->setAuthorAndUserStylesEnabled([preferences authorAndUserStylesEnabled]);
960 if ([preferences userStyleSheetEnabled]) {
961 NSString* location = [[preferences userStyleSheetLocation] _web_originalDataAsString];
962 settings->setUserStyleSheetLocation([NSURL URLWithString:(location ? location : @"")]);
964 settings->setUserStyleSheetLocation([NSURL URLWithString:@""]);
965 settings->setNeedsAdobeFrameReloadingQuirk([self _needsAdobeFrameReloadingQuirk]);
966 settings->setNeedsKeyboardEventDisambiguationQuirks([self _needsKeyboardEventDisambiguationQuirks]);
967 settings->setDefaultDatabaseOriginQuota([preferences defaultDatabaseQuota]);
970 static inline IMP getMethod(id o, SEL s)
972 return [o respondsToSelector:s] ? [o methodForSelector:s] : 0;
975 - (void)_cacheResourceLoadDelegateImplementations
977 WebResourceDelegateImplementationCache *cache = &_private->resourceLoadDelegateImplementations;
978 id delegate = _private->resourceProgressDelegate;
981 bzero(cache, sizeof(WebResourceDelegateImplementationCache));
985 cache->didCancelAuthenticationChallengeFunc = getMethod(delegate, @selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:));
986 cache->didFailLoadingWithErrorFromDataSourceFunc = getMethod(delegate, @selector(webView:resource:didFailLoadingWithError:fromDataSource:));
987 cache->didFinishLoadingFromDataSourceFunc = getMethod(delegate, @selector(webView:resource:didFinishLoadingFromDataSource:));
988 cache->didLoadResourceFromMemoryCacheFunc = getMethod(delegate, @selector(webView:didLoadResourceFromMemoryCache:response:length:fromDataSource:));
989 cache->didReceiveAuthenticationChallengeFunc = getMethod(delegate, @selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:));
990 cache->didReceiveContentLengthFunc = getMethod(delegate, @selector(webView:resource:didReceiveContentLength:fromDataSource:));
991 cache->didReceiveResponseFunc = getMethod(delegate, @selector(webView:resource:didReceiveResponse:fromDataSource:));
992 cache->identifierForRequestFunc = getMethod(delegate, @selector(webView:identifierForInitialRequest:fromDataSource:));
993 cache->plugInFailedWithErrorFunc = getMethod(delegate, @selector(webView:plugInFailedWithError:dataSource:));
994 cache->willCacheResponseFunc = getMethod(delegate, @selector(webView:resource:willCacheResponse:fromDataSource:));
995 cache->willSendRequestFunc = getMethod(delegate, @selector(webView:resource:willSendRequest:redirectResponse:fromDataSource:));
998 WebResourceDelegateImplementationCache* WebViewGetResourceLoadDelegateImplementations(WebView *webView)
1000 static WebResourceDelegateImplementationCache empty;
1003 return &webView->_private->resourceLoadDelegateImplementations;
1006 - (void)_cacheFrameLoadDelegateImplementations
1008 WebFrameLoadDelegateImplementationCache *cache = &_private->frameLoadDelegateImplementations;
1009 id delegate = _private->frameLoadDelegate;
1012 bzero(cache, sizeof(WebFrameLoadDelegateImplementationCache));
1016 cache->didCancelClientRedirectForFrameFunc = getMethod(delegate, @selector(webView:didCancelClientRedirectForFrame:));
1017 cache->didChangeLocationWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didChangeLocationWithinPageForFrame:));
1018 cache->didClearWindowObjectForFrameFunc = getMethod(delegate, @selector(webView:didClearWindowObject:forFrame:));
1019 cache->didCommitLoadForFrameFunc = getMethod(delegate, @selector(webView:didCommitLoadForFrame:));
1020 cache->didFailLoadWithErrorForFrameFunc = getMethod(delegate, @selector(webView:didFailLoadWithError:forFrame:));
1021 cache->didFailProvisionalLoadWithErrorForFrameFunc = getMethod(delegate, @selector(webView:didFailProvisionalLoadWithError:forFrame:));
1022 cache->didFinishDocumentLoadForFrameFunc = getMethod(delegate, @selector(webView:didFinishDocumentLoadForFrame:));
1023 cache->didFinishLoadForFrameFunc = getMethod(delegate, @selector(webView:didFinishLoadForFrame:));
1024 cache->didFirstLayoutInFrameFunc = getMethod(delegate, @selector(webView:didFirstLayoutInFrame:));
1025 cache->didHandleOnloadEventsForFrameFunc = getMethod(delegate, @selector(webView:didHandleOnloadEventsForFrame:));
1026 cache->didReceiveIconForFrameFunc = getMethod(delegate, @selector(webView:didReceiveIcon:forFrame:));
1027 cache->didReceiveServerRedirectForProvisionalLoadForFrameFunc = getMethod(delegate, @selector(webView:didReceiveServerRedirectForProvisionalLoadForFrame:));
1028 cache->didReceiveTitleForFrameFunc = getMethod(delegate, @selector(webView:didReceiveTitle:forFrame:));
1029 cache->didStartProvisionalLoadForFrameFunc = getMethod(delegate, @selector(webView:didStartProvisionalLoadForFrame:));
1030 cache->willCloseFrameFunc = getMethod(delegate, @selector(webView:willCloseFrame:));
1031 cache->willPerformClientRedirectToURLDelayFireDateForFrameFunc = getMethod(delegate, @selector(webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:));
1032 cache->windowScriptObjectAvailableFunc = getMethod(delegate, @selector(webView:windowScriptObjectAvailable:));
1035 WebFrameLoadDelegateImplementationCache* WebViewGetFrameLoadDelegateImplementations(WebView *webView)
1037 static WebFrameLoadDelegateImplementationCache empty;
1040 return &webView->_private->frameLoadDelegateImplementations;
1043 - (id)_policyDelegateForwarder
1045 if (!_private->policyDelegateForwarder)
1046 _private->policyDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->policyDelegate defaultTarget:[WebDefaultPolicyDelegate sharedPolicyDelegate] catchExceptions:_private->catchesDelegateExceptions];
1047 return _private->policyDelegateForwarder;
1050 - (id)_UIDelegateForwarder
1052 if (!_private->UIDelegateForwarder)
1053 _private->UIDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->UIDelegate defaultTarget:[WebDefaultUIDelegate sharedUIDelegate] catchExceptions:_private->catchesDelegateExceptions];
1054 return _private->UIDelegateForwarder;
1057 - (id)_editingDelegateForwarder
1059 // This can be called during window deallocation by QTMovieView in the QuickTime Cocoa Plug-in.
1060 // Not sure if that is a bug or not.
1064 if (!_private->editingDelegateForwarder)
1065 _private->editingDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->editingDelegate defaultTarget:[WebDefaultEditingDelegate sharedEditingDelegate] catchExceptions:_private->catchesDelegateExceptions];
1066 return _private->editingDelegateForwarder;
1069 - (id)_scriptDebugDelegateForwarder
1071 if (!_private->scriptDebugDelegateForwarder)
1072 _private->scriptDebugDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->scriptDebugDelegate defaultTarget:[WebDefaultScriptDebugDelegate sharedScriptDebugDelegate] catchExceptions:_private->catchesDelegateExceptions];
1073 return _private->scriptDebugDelegateForwarder;
1076 - (void)_closeWindow
1078 [[self _UIDelegateForwarder] webViewClose:self];
1081 + (void)_unregisterViewClassAndRepresentationClassForMIMEType:(NSString *)MIMEType;
1083 [[WebFrameView _viewTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType];
1084 [[WebDataSource _repTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType];
1086 // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
1087 // in the WebCore MIMEType registry. For now we're doing this in a safe, limited manner
1088 // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
1089 MIMETypeRegistry::getSupportedNonImageMIMETypes().remove(MIMEType);
1092 + (void)_registerViewClass:(Class)viewClass representationClass:(Class)representationClass forURLScheme:(NSString *)URLScheme;
1094 NSString *MIMEType = [self _generatedMIMETypeForURLScheme:URLScheme];
1095 [self registerViewClass:viewClass representationClass:representationClass forMIMEType:MIMEType];
1097 // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
1098 // in the WebCore MIMEType registry. For now we're doing this in a safe, limited manner
1099 // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
1100 if ([viewClass class] == [WebHTMLView class])
1101 MIMETypeRegistry::getSupportedNonImageMIMETypes().add(MIMEType);
1103 // This is used to make _representationExistsForURLScheme faster.
1104 // Without this set, we'd have to create the MIME type each time.
1105 if (schemesWithRepresentationsSet == nil) {
1106 schemesWithRepresentationsSet = [[NSMutableSet alloc] init];
1108 [schemesWithRepresentationsSet addObject:[[[URLScheme lowercaseString] copy] autorelease]];
1111 + (NSString *)_generatedMIMETypeForURLScheme:(NSString *)URLScheme
1113 return [@"x-apple-web-kit/" stringByAppendingString:[URLScheme lowercaseString]];
1116 + (BOOL)_representationExistsForURLScheme:(NSString *)URLScheme
1118 return [schemesWithRepresentationsSet containsObject:[URLScheme lowercaseString]];
1121 + (BOOL)_canHandleRequest:(NSURLRequest *)request
1123 // FIXME: If <rdar://problem/5217309> gets fixed, this check can be removed
1127 if ([NSURLConnection canHandleRequest:request])
1130 NSString *scheme = [[request URL] scheme];
1132 if ([self _representationExistsForURLScheme:scheme])
1135 return ([scheme _webkit_isCaseInsensitiveEqualToString:@"applewebdata"]);
1138 + (NSString *)_decodeData:(NSData *)data
1140 HTMLNames::init(); // this method is used for importing bookmarks at startup, so HTMLNames are likely to be uninitialized yet
1141 RefPtr<TextResourceDecoder> decoder = new TextResourceDecoder("text/html"); // bookmark files are HTML
1142 String result = decoder->decode(static_cast<const char*>([data bytes]), [data length]);
1143 result += decoder->flush();
1147 - (void)_pushPerformingProgrammaticFocus
1149 _private->programmaticFocusCount++;
1152 - (void)_popPerformingProgrammaticFocus
1154 _private->programmaticFocusCount--;
1157 - (BOOL)_isPerformingProgrammaticFocus
1159 return _private->programmaticFocusCount != 0;
1162 - (void)_didChangeValueForKey: (NSString *)key
1164 LOG (Bindings, "calling didChangeValueForKey: %@", key);
1165 [self didChangeValueForKey: key];
1168 - (void)_willChangeValueForKey: (NSString *)key
1170 LOG (Bindings, "calling willChangeValueForKey: %@", key);
1171 [self willChangeValueForKey: key];
1174 + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key {
1175 static NSSet *manualNotifyKeys = nil;
1176 if (!manualNotifyKeys)
1177 manualNotifyKeys = [[NSSet alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey,
1178 _WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, _WebMainFrameDocumentKey, nil];
1179 if ([manualNotifyKeys containsObject:key])
1184 - (NSArray *)_declaredKeys {
1185 static NSArray *declaredKeys = nil;
1187 declaredKeys = [[NSArray alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey,
1188 _WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, _WebMainFrameDocumentKey, nil];
1189 return declaredKeys;
1192 - (void)setObservationInfo:(void *)info
1194 _private->observationInfo = info;
1197 - (void *)observationInfo
1199 return _private->observationInfo;
1202 - (void)_willChangeBackForwardKeys
1204 [self _willChangeValueForKey: _WebCanGoBackKey];
1205 [self _willChangeValueForKey: _WebCanGoForwardKey];
1208 - (void)_didChangeBackForwardKeys
1210 [self _didChangeValueForKey: _WebCanGoBackKey];
1211 [self _didChangeValueForKey: _WebCanGoForwardKey];
1214 - (void)_didStartProvisionalLoadForFrame:(WebFrame *)frame
1216 [self _willChangeBackForwardKeys];
1217 if (frame == [self mainFrame]){
1218 // Force an observer update by sending a will/did.
1219 [self _willChangeValueForKey: _WebIsLoadingKey];
1220 [self _didChangeValueForKey: _WebIsLoadingKey];
1222 [self _willChangeValueForKey: _WebMainFrameURLKey];
1225 [NSApp setWindowsNeedUpdate:YES];
1228 - (void)_didCommitLoadForFrame:(WebFrame *)frame
1230 if (frame == [self mainFrame])
1231 [self _didChangeValueForKey: _WebMainFrameURLKey];
1232 [NSApp setWindowsNeedUpdate:YES];
1235 - (void)_didFinishLoadForFrame:(WebFrame *)frame
1237 [self _didChangeBackForwardKeys];
1238 if (frame == [self mainFrame]){
1239 // Force an observer update by sending a will/did.
1240 [self _willChangeValueForKey: _WebIsLoadingKey];
1241 [self _didChangeValueForKey: _WebIsLoadingKey];
1243 [NSApp setWindowsNeedUpdate:YES];
1246 - (void)_didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
1248 [self _didChangeBackForwardKeys];
1249 if (frame == [self mainFrame]){
1250 // Force an observer update by sending a will/did.
1251 [self _willChangeValueForKey: _WebIsLoadingKey];
1252 [self _didChangeValueForKey: _WebIsLoadingKey];
1254 [NSApp setWindowsNeedUpdate:YES];
1257 - (void)_didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
1259 [self _didChangeBackForwardKeys];
1260 if (frame == [self mainFrame]){
1261 // Force an observer update by sending a will/did.
1262 [self _willChangeValueForKey: _WebIsLoadingKey];
1263 [self _didChangeValueForKey: _WebIsLoadingKey];
1265 [self _didChangeValueForKey: _WebMainFrameURLKey];
1267 [NSApp setWindowsNeedUpdate:YES];
1270 - (void)_reloadForPluginChanges
1272 [[self mainFrame] _reloadForPluginChanges];
1275 - (NSCachedURLResponse *)_cachedResponseForURL:(NSURL *)URL
1277 NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:URL];
1278 [request _web_setHTTPUserAgent:[self userAgentForURL:URL]];
1279 NSCachedURLResponse *cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:request];
1281 return cachedResponse;
1284 - (void)_writeImageForElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
1286 NSURL *linkURL = [element objectForKey:WebElementLinkURLKey];
1287 DOMElement *domElement = [element objectForKey:WebElementDOMNodeKey];
1288 [pasteboard _web_writeImage:(NSImage *)(domElement ? nil : [element objectForKey:WebElementImageKey])
1290 URL:linkURL ? linkURL : (NSURL *)[element objectForKey:WebElementImageURLKey]
1291 title:[element objectForKey:WebElementImageAltStringKey]
1292 archive:[[element objectForKey:WebElementDOMNodeKey] webArchive]
1297 - (void)_writeLinkElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
1299 [pasteboard _web_writeURL:[element objectForKey:WebElementLinkURLKey]
1300 andTitle:[element objectForKey:WebElementLinkLabelKey]
1304 - (void)_setInitiatedDrag:(BOOL)initiatedDrag
1306 if (!_private->page)
1308 _private->page->dragController()->setDidInitiateDrag(initiatedDrag);
1311 #define DASHBOARD_CONTROL_LABEL @"control"
1313 - (void)_addScrollerDashboardRegions:(NSMutableDictionary *)regions from:(NSArray *)views
1315 // Add scroller regions for NSScroller and KWQScrollBar
1316 int i, count = [views count];
1318 for (i = 0; i < count; i++) {
1319 NSView *aView = [views objectAtIndex:i];
1321 if ([aView isKindOfClass:[NSScroller class]] ||
1322 [aView isKindOfClass:NSClassFromString (@"KWQScrollBar")]) {
1323 NSRect bounds = [aView bounds];
1324 NSRect adjustedBounds;
1325 adjustedBounds.origin = [self convertPoint:bounds.origin fromView:aView];
1326 adjustedBounds.origin.y = [self bounds].size.height - adjustedBounds.origin.y;
1328 // AppKit has horrible hack of placing absent scrollers at -100,-100
1329 if (adjustedBounds.origin.y == -100)
1331 adjustedBounds.size = bounds.size;
1332 NSRect clip = [aView visibleRect];
1333 NSRect adjustedClip;
1334 adjustedClip.origin = [self convertPoint:clip.origin fromView:aView];
1335 adjustedClip.origin.y = [self bounds].size.height - adjustedClip.origin.y;
1336 adjustedClip.size = clip.size;
1337 WebDashboardRegion *aRegion =
1338 [[[WebDashboardRegion alloc] initWithRect:adjustedBounds
1339 clip:adjustedClip type:WebDashboardRegionTypeScrollerRectangle] autorelease];
1340 NSMutableArray *scrollerRegions;
1341 scrollerRegions = [regions objectForKey:DASHBOARD_CONTROL_LABEL];
1342 if (!scrollerRegions) {
1343 scrollerRegions = [NSMutableArray array];
1344 [regions setObject:scrollerRegions forKey:DASHBOARD_CONTROL_LABEL];
1346 [scrollerRegions addObject:aRegion];
1348 [self _addScrollerDashboardRegions:regions from:[aView subviews]];
1352 - (void)_addScrollerDashboardRegions:(NSMutableDictionary *)regions
1354 [self _addScrollerDashboardRegions:regions from:[self subviews]];
1357 - (NSDictionary *)_dashboardRegions
1359 // Only return regions from main frame.
1360 Frame* mainFrame = [[[self mainFrame] _bridge] _frame];
1363 NSMutableDictionary *regions = mainFrame->dashboardRegionsDictionary();
1364 [self _addScrollerDashboardRegions:regions];
1368 - (void)_setDashboardBehavior:(WebDashboardBehavior)behavior to:(BOOL)flag
1370 // FIXME: Remove this blanket assignment once Dashboard and Dashcode implement
1371 // specific support for the backward compatibility mode flag.
1372 if (behavior == WebDashboardBehaviorAllowWheelScrolling && flag == NO && _private->page)
1373 _private->page->settings()->setUsesDashboardBackwardCompatibilityMode(true);
1376 case WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows: {
1377 _private->dashboardBehaviorAlwaysSendMouseEventsToAllWindows = flag;
1380 case WebDashboardBehaviorAlwaysSendActiveNullEventsToPlugIns: {
1381 _private->dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns = flag;
1384 case WebDashboardBehaviorAlwaysAcceptsFirstMouse: {
1385 _private->dashboardBehaviorAlwaysAcceptsFirstMouse = flag;
1388 case WebDashboardBehaviorAllowWheelScrolling: {
1389 _private->dashboardBehaviorAllowWheelScrolling = flag;
1392 case WebDashboardBehaviorUseBackwardCompatibilityMode: {
1394 _private->page->settings()->setUsesDashboardBackwardCompatibilityMode(flag);
1400 - (BOOL)_dashboardBehavior:(WebDashboardBehavior)behavior
1403 case WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows: {
1404 return _private->dashboardBehaviorAlwaysSendMouseEventsToAllWindows;
1406 case WebDashboardBehaviorAlwaysSendActiveNullEventsToPlugIns: {
1407 return _private->dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns;
1409 case WebDashboardBehaviorAlwaysAcceptsFirstMouse: {
1410 return _private->dashboardBehaviorAlwaysAcceptsFirstMouse;
1412 case WebDashboardBehaviorAllowWheelScrolling: {
1413 return _private->dashboardBehaviorAllowWheelScrolling;
1415 case WebDashboardBehaviorUseBackwardCompatibilityMode: {
1416 return _private->page && _private->page->settings()->usesDashboardBackwardCompatibilityMode();
1422 + (void)_setShouldUseFontSmoothing:(BOOL)f
1424 WebCoreSetShouldUseFontSmoothing(f);
1427 + (BOOL)_shouldUseFontSmoothing
1429 return WebCoreShouldUseFontSmoothing();
1432 + (void)_setUsesTestModeFocusRingColor:(BOOL)f
1434 setUsesTestModeFocusRingColor(f);
1437 + (BOOL)_usesTestModeFocusRingColor
1439 return usesTestModeFocusRingColor();
1442 // This is only used by older versions of Safari and should be removed in a future release.
1443 + (NSString *)_minimumRequiredSafariBuildNumber
1448 - (void)setAlwaysShowVerticalScroller:(BOOL)flag
1450 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
1452 [scrollview setVerticalScrollingMode:WebCoreScrollbarAlwaysOn andLock:YES];
1454 [scrollview setVerticalScrollingModeLocked:NO];
1455 [scrollview setVerticalScrollingMode:WebCoreScrollbarAuto];
1459 - (BOOL)alwaysShowVerticalScroller
1461 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
1462 return [scrollview verticalScrollingModeLocked] && [scrollview verticalScrollingMode] == WebCoreScrollbarAlwaysOn;
1465 - (void)setAlwaysShowHorizontalScroller:(BOOL)flag
1467 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
1469 [scrollview setHorizontalScrollingMode:WebCoreScrollbarAlwaysOn andLock:YES];
1471 [scrollview setHorizontalScrollingModeLocked:NO];
1472 [scrollview setHorizontalScrollingMode:WebCoreScrollbarAuto];
1476 - (void)setProhibitsMainFrameScrolling:(BOOL)prohibits
1478 Frame* mainFrame = [[[self mainFrame] _bridge] _frame];
1480 mainFrame->setProhibitsScrolling(prohibits);
1483 - (BOOL)alwaysShowHorizontalScroller
1485 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
1486 return [scrollview horizontalScrollingModeLocked] && [scrollview horizontalScrollingMode] == WebCoreScrollbarAlwaysOn;
1489 - (void)_setInViewSourceMode:(BOOL)flag
1491 Frame* mainFrame = [[[self mainFrame] _bridge] _frame];
1493 mainFrame->setInViewSourceMode(flag);
1496 - (BOOL)_inViewSourceMode
1498 Frame* mainFrame = [[[self mainFrame] _bridge] _frame];
1499 return mainFrame && mainFrame->inViewSourceMode();
1502 - (void)_setUseFastImageScalingMode:(BOOL)flag
1504 if (_private->page && _private->page->inLowQualityImageInterpolationMode() != flag) {
1505 _private->page->setInLowQualityImageInterpolationMode(flag);
1506 [self setNeedsDisplay:YES];
1510 - (BOOL)_inFastImageScalingMode
1513 return _private->page->inLowQualityImageInterpolationMode();
1517 - (void)_setAdditionalWebPlugInPaths:(NSArray *)newPaths
1519 if (!_private->pluginDatabase)
1520 _private->pluginDatabase = [[WebPluginDatabase alloc] init];
1522 [_private->pluginDatabase setPlugInPaths:newPaths];
1523 [_private->pluginDatabase refresh];
1526 - (void)_attachScriptDebuggerToAllFrames
1528 for (Frame* frame = core([self mainFrame]); frame; frame = frame->tree()->traverseNext())
1529 [kit(frame) _attachScriptDebugger];
1532 - (void)_detachScriptDebuggerFromAllFrames
1534 for (Frame* frame = core([self mainFrame]); frame; frame = frame->tree()->traverseNext())
1535 [kit(frame) _detachScriptDebugger];
1538 - (void)setBackgroundColor:(NSColor *)backgroundColor
1540 if ([_private->backgroundColor isEqual:backgroundColor])
1543 id old = _private->backgroundColor;
1544 _private->backgroundColor = [backgroundColor retain];
1547 [[self mainFrame] _updateBackground];
1550 - (NSColor *)backgroundColor
1552 return _private->backgroundColor;
1555 - (BOOL)defersCallbacks
1557 if (!_private->page)
1559 return _private->page->defersLoading();
1562 - (void)setDefersCallbacks:(BOOL)defer
1564 if (!_private->page)
1566 return _private->page->setDefersLoading(defer);
1569 // For backwards compatibility with the WebBackForwardList API, we honor both
1570 // a per-WebView and a per-preferences setting for whether to use the page cache.
1572 - (BOOL)usesPageCache
1574 return _private->usesPageCache && [[self preferences] usesPageCache];
1577 - (void)setUsesPageCache:(BOOL)usesPageCache
1579 _private->usesPageCache = usesPageCache;
1581 // Post a notification so the WebCore settings update.
1582 [[self preferences] _postPreferencesChangesNotification];
1585 - (void)handleAuthenticationForResource:(id)identifier challenge:(NSURLAuthenticationChallenge *)challenge fromDataSource:(WebDataSource *)dataSource
1587 NSWindow *window = [self hostWindow] ? [self hostWindow] : [self window];
1588 [[WebPanelAuthenticationHandler sharedHandler] startAuthentication:challenge window:window];
1591 - (void)_clearUndoRedoOperations
1593 if (!_private->page)
1595 _private->page->clearUndoRedoOperations();
1598 - (void)_setCatchesDelegateExceptions:(BOOL)f
1600 _private->catchesDelegateExceptions = f;
1603 - (BOOL)_catchesDelegateExceptions
1605 return _private->catchesDelegateExceptions;
1610 @implementation _WebSafeForwarder
1612 // Used to send messages to delegates that implement informal protocols.
1614 - (id)initWithTarget:(id)t defaultTarget:(id)dt catchExceptions:(BOOL)c
1616 self = [super init];
1619 target = t; // Non retained.
1621 catchExceptions = c;
1625 - (void)forwardInvocation:(NSInvocation *)invocation
1627 if ([target respondsToSelector:[invocation selector]]) {
1628 if (catchExceptions) {
1630 [invocation invokeWithTarget:target];
1631 } @catch(id exception) {
1632 ReportDiscardedDelegateException([invocation selector], exception);
1635 [invocation invokeWithTarget:target];
1639 if ([defaultTarget respondsToSelector:[invocation selector]])
1640 [invocation invokeWithTarget:defaultTarget];
1642 // Do nothing quietly if method not implemented.
1645 - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
1647 return [defaultTarget methodSignatureForSelector:aSelector];
1652 @implementation WebView
1656 static BOOL initialized = NO;
1661 #ifdef REMOVE_SAFARI_DOM_TREE_DEBUG_ITEM
1662 // This prevents open source users from crashing when using the Show DOM Tree menu item in Safari 2.
1663 // FIXME: remove this when we no longer need to support Safari 2.
1664 if ([[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.Safari"] && [[NSUserDefaults standardUserDefaults] boolForKey:@"IncludeDebugMenu"])
1665 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_finishedLaunching) name:NSApplicationDidFinishLaunchingNotification object:NSApp];
1668 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_applicationWillTerminate) name:NSApplicationWillTerminateNotification object:NSApp];
1669 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:) name:WebPreferencesChangedNotification object:nil];
1670 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesRemovedNotification:) name:WebPreferencesRemovedNotification object:nil];
1673 + (void)_applicationWillTerminate
1675 applicationIsTerminating = YES;
1676 if (!pluginDatabaseClientCount)
1677 [WebPluginDatabase closeSharedDatabase];
1680 #ifdef REMOVE_SAFARI_DOM_TREE_DEBUG_ITEM
1681 // FIXME: remove this when it is no longer needed to prevent Safari from crashing
1682 + (void)_finishedLaunching
1684 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_removeDOMTreeMenuItem:) name:NSMenuDidAddItemNotification object:[NSApp mainMenu]];
1685 [[NSNotificationCenter defaultCenter] removeObserver:self name:NSApplicationDidFinishLaunchingNotification object:NSApp];
1688 +(void)_removeDOMTreeMenuItem:(NSNotification *)notification
1690 NSMenu *debugMenu = [[[[NSApp mainMenu] itemArray] lastObject] submenu];
1691 NSMenuItem *domTree = [debugMenu itemWithTitle:@"Show DOM Tree"];
1693 [debugMenu removeItem:domTree];
1694 [[NSNotificationCenter defaultCenter] removeObserver:self name:NSMenuDidAddItemNotification object:[NSApp mainMenu]];
1698 + (BOOL)canShowMIMEType:(NSString *)MIMEType
1700 return [self _viewClass:nil andRepresentationClass:nil forMIMEType:MIMEType];
1703 - (WebBasePluginPackage *)_pluginForMIMEType:(NSString *)MIMEType
1705 WebBasePluginPackage *pluginPackage = [[WebPluginDatabase sharedDatabase] pluginForMIMEType:MIMEType];
1707 return pluginPackage;
1709 if (_private->pluginDatabase)
1710 return [_private->pluginDatabase pluginForMIMEType:MIMEType];
1715 - (WebBasePluginPackage *)_pluginForExtension:(NSString *)extension
1717 WebBasePluginPackage *pluginPackage = [[WebPluginDatabase sharedDatabase] pluginForExtension:extension];
1719 return pluginPackage;
1721 if (_private->pluginDatabase)
1722 return [_private->pluginDatabase pluginForExtension:extension];
1727 - (BOOL)_isMIMETypeRegisteredAsPlugin:(NSString *)MIMEType
1729 if ([[WebPluginDatabase sharedDatabase] isMIMETypeRegistered:MIMEType])
1732 if (_private->pluginDatabase && [_private->pluginDatabase isMIMETypeRegistered:MIMEType])
1738 + (BOOL)canShowMIMETypeAsHTML:(NSString *)MIMEType
1740 return [WebFrameView _canShowMIMETypeAsHTML:MIMEType];
1743 + (NSArray *)MIMETypesShownAsHTML
1745 NSMutableDictionary *viewTypes = [WebFrameView _viewTypesAllowImageTypeOmission:YES];
1746 NSEnumerator *enumerator = [viewTypes keyEnumerator];
1748 NSMutableArray *array = [[[NSMutableArray alloc] init] autorelease];
1750 while ((key = [enumerator nextObject])) {
1751 if ([viewTypes objectForKey:key] == [WebHTMLView class])
1752 [array addObject:key];
1758 + (void)setMIMETypesShownAsHTML:(NSArray *)MIMETypes
1760 NSDictionary *viewTypes = [[WebFrameView _viewTypesAllowImageTypeOmission:YES] copy];
1761 NSEnumerator *enumerator = [viewTypes keyEnumerator];
1763 while ((key = [enumerator nextObject])) {
1764 if ([viewTypes objectForKey:key] == [WebHTMLView class])
1765 [WebView _unregisterViewClassAndRepresentationClassForMIMEType:key];
1768 int i, count = [MIMETypes count];
1769 for (i = 0; i < count; i++) {
1770 [WebView registerViewClass:[WebHTMLView class]
1771 representationClass:[WebHTMLRepresentation class]
1772 forMIMEType:[MIMETypes objectAtIndex:i]];
1774 [viewTypes release];
1777 + (NSURL *)URLFromPasteboard:(NSPasteboard *)pasteboard
1779 return [pasteboard _web_bestURL];
1782 + (NSString *)URLTitleFromPasteboard:(NSPasteboard *)pasteboard
1784 return [pasteboard stringForType:WebURLNamePboardType];
1787 + (void)registerURLSchemeAsLocal:(NSString *)protocol
1789 FrameLoader::registerURLSchemeAsLocal(protocol);
1792 - (void)_registerDraggedTypes
1794 NSArray *editableTypes = [WebHTMLView _insertablePasteboardTypes];
1795 NSArray *URLTypes = [NSPasteboard _web_dragTypesForURL];
1796 NSMutableSet *types = [[NSMutableSet alloc] initWithArray:editableTypes];
1797 [types addObjectsFromArray:URLTypes];
1798 [self registerForDraggedTypes:[types allObjects]];
1802 - (void)_commonInitializationWithFrameName:(NSString *)frameName groupName:(NSString *)groupName
1804 WebPreferences *standardPreferences = [WebPreferences standardPreferences];
1805 [standardPreferences willAddToWebView];
1807 _private->preferences = [standardPreferences retain];
1808 _private->catchesDelegateExceptions = YES;
1809 _private->mainFrameDocumentReady = NO;
1810 _private->drawsBackground = YES;
1811 _private->smartInsertDeleteEnabled = YES;
1812 _private->backgroundColor = [[NSColor whiteColor] retain];
1814 NSRect f = [self frame];
1815 WebFrameView *frameView = [[WebFrameView alloc] initWithFrame: NSMakeRect(0,0,f.size.width,f.size.height)];
1816 [frameView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
1817 [self addSubview:frameView];
1818 [frameView release];
1820 WebKitInitializeLoggingChannelsIfNecessary();
1821 WebCore::InitializeLoggingChannelsIfNecessary();
1822 [WebHistoryItem initWindowWatcherIfNecessary];
1823 WebKitInitializeDatabasesIfNecessary();
1825 _private->page = new Page(new WebChromeClient(self), new WebContextMenuClient(self), new WebEditorClient(self), new WebDragClient(self), new WebInspectorClient(self));
1826 [[[WebFrameBridge alloc] initMainFrameWithPage:_private->page frameName:frameName frameView:frameView] release];
1828 [self _addToAllWebViewsSet];
1829 [self setGroupName:groupName];
1831 // If there's already a next key view (e.g., from a nib), wire it up to our
1832 // contained frame view. In any case, wire our next key view up to the our
1833 // contained frame view. This works together with our becomeFirstResponder
1834 // and setNextKeyView overrides.
1835 NSView *nextKeyView = [self nextKeyView];
1836 if (nextKeyView != nil && nextKeyView != frameView) {
1837 [frameView setNextKeyView:nextKeyView];
1839 [super setNextKeyView:frameView];
1843 [self _registerDraggedTypes];
1845 // initialize WebScriptDebugServer here so listeners can register before any pages are loaded.
1846 if ([WebView _scriptDebuggerEnabled])
1847 [WebScriptDebugServer sharedScriptDebugServer];
1849 WebPreferences *prefs = [self preferences];
1850 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:)
1851 name:WebPreferencesChangedNotification object:prefs];
1853 // Post a notification so the WebCore settings update.
1854 [[self preferences] _postPreferencesChangesNotification];
1856 if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_LOCAL_RESOURCE_SECURITY_RESTRICTION))
1857 FrameLoader::setRestrictAccessToLocal(false);
1860 - (id)initWithFrame:(NSRect)f
1862 return [self initWithFrame:f frameName:nil groupName:nil];
1865 - (id)initWithFrame:(NSRect)f frameName:(NSString *)frameName groupName:(NSString *)groupName;
1867 self = [super initWithFrame:f];
1871 #ifdef ENABLE_WEBKIT_UNSET_DYLD_FRAMEWORK_PATH
1872 // DYLD_FRAMEWORK_PATH is used so Safari will load the development version of WebKit, which
1873 // may not work with other WebKit applications. Unsetting DYLD_FRAMEWORK_PATH removes the
1874 // need for Safari to unset it to prevent it from being passed to applications it launches.
1875 // Unsetting it when a WebView is first created is as good a place as any.
1876 // See <http://bugs.webkit.org/show_bug.cgi?id=4286> for more details.
1877 if (getenv("WEBKIT_UNSET_DYLD_FRAMEWORK_PATH")) {
1878 unsetenv("DYLD_FRAMEWORK_PATH");
1879 unsetenv("WEBKIT_UNSET_DYLD_FRAMEWORK_PATH");
1883 _private = [[WebViewPrivate alloc] init];
1884 [self _commonInitializationWithFrameName:frameName groupName:groupName];
1885 [self setMaintainsBackForwardList: YES];
1889 - (id)initWithCoder:(NSCoder *)decoder
1891 WebView *result = nil;
1894 NSString *frameName;
1895 NSString *groupName;
1896 WebPreferences *preferences;
1897 BOOL useBackForwardList = NO;
1898 BOOL allowsUndo = YES;
1900 result = [super initWithCoder:decoder];
1901 result->_private = [[WebViewPrivate alloc] init];
1903 // We don't want any of the archived subviews. The subviews will always
1904 // be created in _commonInitializationFrameName:groupName:.
1905 [[result subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
1907 if ([decoder allowsKeyedCoding]) {
1908 frameName = [decoder decodeObjectForKey:@"FrameName"];
1909 groupName = [decoder decodeObjectForKey:@"GroupName"];
1910 preferences = [decoder decodeObjectForKey:@"Preferences"];
1911 useBackForwardList = [decoder decodeBoolForKey:@"UseBackForwardList"];
1912 if ([decoder containsValueForKey:@"AllowsUndo"])
1913 allowsUndo = [decoder decodeBoolForKey:@"AllowsUndo"];
1916 [decoder decodeValueOfObjCType:@encode(int) at:&version];
1917 frameName = [decoder decodeObject];
1918 groupName = [decoder decodeObject];
1919 preferences = [decoder decodeObject];
1921 [decoder decodeValuesOfObjCTypes:"c", &useBackForwardList];
1922 // The allowsUndo field is no longer written out in encodeWithCoder, but since there are
1923 // version 3 NIBs that have this field encoded, we still need to read it in.
1925 [decoder decodeValuesOfObjCTypes:"c", &allowsUndo];
1928 if (![frameName isKindOfClass:[NSString class]])
1930 if (![groupName isKindOfClass:[NSString class]])
1932 if (![preferences isKindOfClass:[WebPreferences class]])
1935 LOG(Encoding, "FrameName = %@, GroupName = %@, useBackForwardList = %d\n", frameName, groupName, (int)useBackForwardList);
1936 [result _commonInitializationWithFrameName:frameName groupName:groupName];
1937 [result page]->backForwardList()->setEnabled(useBackForwardList);
1938 result->_private->allowsUndo = allowsUndo;
1940 [result setPreferences:preferences];
1941 } @catch (NSException *localException) {
1949 - (void)encodeWithCoder:(NSCoder *)encoder
1951 // Set asside the subviews before we archive. We don't want to archive any subviews.
1952 // The subviews will always be created in _commonInitializationFrameName:groupName:.
1953 id originalSubviews = _subviews;
1956 [super encodeWithCoder:encoder];
1958 // Restore the subviews we set aside.
1959 _subviews = originalSubviews;
1961 BOOL useBackForwardList = _private->page && _private->page->backForwardList()->enabled();
1962 if ([encoder allowsKeyedCoding]) {
1963 [encoder encodeObject:[[self mainFrame] name] forKey:@"FrameName"];
1964 [encoder encodeObject:[self groupName] forKey:@"GroupName"];
1965 [encoder encodeObject:[self preferences] forKey:@"Preferences"];
1966 [encoder encodeBool:useBackForwardList forKey:@"UseBackForwardList"];
1967 [encoder encodeBool:_private->allowsUndo forKey:@"AllowsUndo"];
1969 int version = WebViewVersion;
1970 [encoder encodeValueOfObjCType:@encode(int) at:&version];
1971 [encoder encodeObject:[[self mainFrame] name]];
1972 [encoder encodeObject:[self groupName]];
1973 [encoder encodeObject:[self preferences]];
1974 [encoder encodeValuesOfObjCTypes:"c", &useBackForwardList];
1975 // DO NOT encode any new fields here, doing so will break older WebKit releases.
1978 LOG(Encoding, "FrameName = %@, GroupName = %@, useBackForwardList = %d\n", [[self mainFrame] name], [self groupName], (int)useBackForwardList);
1983 // call close to ensure we tear-down completely
1984 // this maintains our old behavior for existing applications
1990 // [super dealloc] can end up dispatching against _private (3466082)
1998 ASSERT(_private->closed);
2010 - (void)setShouldCloseWithWindow:(BOOL)close
2012 _private->shouldCloseWithWindow = close;
2015 - (BOOL)shouldCloseWithWindow
2017 return _private->shouldCloseWithWindow;
2020 - (void)viewWillMoveToWindow:(NSWindow *)window
2022 // Don't do anything if we aren't initialized. This happens when decoding a WebView.
2027 [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowWillCloseNotification object:[self window]];
2030 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillClose:) name:NSWindowWillCloseNotification object:window];
2032 // Ensure that we will receive the events that WebHTMLView (at least) needs. It's expensive enough
2033 // that we don't want to call it over and over.
2034 [window setAcceptsMouseMovedEvents:YES];
2035 WKSetNSWindowShouldPostEventNotifications(window, YES);
2039 - (void)_windowWillClose:(NSNotification *)notification
2041 if ([self shouldCloseWithWindow] && ([self window] == [self hostWindow] || ([self window] && ![self hostWindow]) || (![self window] && [self hostWindow])))
2045 - (void)setPreferences:(WebPreferences *)prefs
2048 prefs = [WebPreferences standardPreferences];
2050 if (_private->preferences == prefs)
2053 [prefs willAddToWebView];
2055 WebPreferences *oldPrefs = _private->preferences;
2057 [[NSNotificationCenter defaultCenter] removeObserver:self name:WebPreferencesChangedNotification object:[self preferences]];
2058 [WebPreferences _removeReferenceForIdentifier:[oldPrefs identifier]];
2060 _private->preferences = [prefs retain];
2062 // After registering for the notification, post it so the WebCore settings update.
2063 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:)
2064 name:WebPreferencesChangedNotification object:[self preferences]];
2065 [[self preferences] _postPreferencesChangesNotification];
2067 [oldPrefs didRemoveFromWebView];
2071 - (WebPreferences *)preferences
2073 return _private->preferences;
2076 - (void)setPreferencesIdentifier:(NSString *)anIdentifier
2078 if (!_private->closed && ![anIdentifier isEqual:[[self preferences] identifier]]) {
2079 WebPreferences *prefs = [[WebPreferences alloc] initWithIdentifier:anIdentifier];
2080 [self setPreferences:prefs];
2085 - (NSString *)preferencesIdentifier
2087 return [[self preferences] identifier];
2091 - (void)setUIDelegate:delegate
2093 _private->UIDelegate = delegate;
2094 [_private->UIDelegateForwarder release];
2095 _private->UIDelegateForwarder = nil;
2100 return _private->UIDelegate;
2103 - (void)setResourceLoadDelegate: delegate
2105 _private->resourceProgressDelegate = delegate;
2106 [self _cacheResourceLoadDelegateImplementations];
2109 - resourceLoadDelegate
2111 return _private->resourceProgressDelegate;
2114 - (void)setDownloadDelegate: delegate
2116 _private->downloadDelegate = delegate;
2122 return _private->downloadDelegate;
2125 - (void)setPolicyDelegate:delegate
2127 _private->policyDelegate = delegate;
2128 [_private->policyDelegateForwarder release];
2129 _private->policyDelegateForwarder = nil;
2134 return _private->policyDelegate;
2137 - (void)setFrameLoadDelegate:delegate
2139 _private->frameLoadDelegate = delegate;
2140 [self _cacheFrameLoadDelegateImplementations];
2142 // If this delegate wants callbacks for icons, fire up the icon database.
2143 if (_private->frameLoadDelegateImplementations.didReceiveIconForFrameFunc)
2144 [WebIconDatabase sharedIconDatabase];
2149 return _private->frameLoadDelegate;
2152 - (WebFrame *)mainFrame
2154 // This can be called in initialization, before _private has been set up (3465613)
2157 if (!_private->page)
2159 return kit(_private->page->mainFrame());
2162 - (WebFrame *)selectedFrame
2164 // If the first responder is a view in our tree, we get the frame containing the first responder.
2165 // This is faster than searching the frame hierarchy, and will give us a result even in the case
2166 // where the focused frame doesn't actually contain a selection.
2167 WebFrame *focusedFrame = [self _focusedFrame];
2169 return focusedFrame;
2171 // If the first responder is outside of our view tree, we search for a frame containing a selection.
2172 // There should be at most only one of these.
2173 return [[self mainFrame] _findFrameWithSelection];
2176 - (WebBackForwardList *)backForwardList
2178 if (!_private->page)
2180 if (!_private->page->backForwardList()->enabled())
2182 return kit(_private->page->backForwardList());
2185 - (void)setMaintainsBackForwardList: (BOOL)flag
2187 if (!_private->page)
2189 _private->page->backForwardList()->setEnabled(flag);
2194 if (!_private->page)
2197 return _private->page->goBack();
2202 if (!_private->page)
2205 return _private->page->goForward();
2208 - (BOOL)goToBackForwardItem:(WebHistoryItem *)item
2210 if (!_private->page)
2213 _private->page->goToItem(core(item), FrameLoadTypeIndexedBackForward);
2217 - (void)setTextSizeMultiplier:(float)m
2219 // NOTE: This has no visible effect when viewing a PDF (see <rdar://problem/4737380>)
2220 if (_private->textSizeMultiplier == m)
2223 _private->textSizeMultiplier = m;
2224 [self _notifyTextSizeMultiplierChanged];
2227 - (float)textSizeMultiplier
2229 return _private->textSizeMultiplier;
2232 - (void)setApplicationNameForUserAgent:(NSString *)applicationName
2234 NSString *name = [applicationName copy];
2235 [_private->applicationNameForUserAgent release];
2236 _private->applicationNameForUserAgent = name;
2237 if (!_private->userAgentOverridden)
2238 *_private->userAgent = String();
2241 - (NSString *)applicationNameForUserAgent
2243 return [[_private->applicationNameForUserAgent retain] autorelease];
2246 - (void)setCustomUserAgent:(NSString *)userAgentString
2248 *_private->userAgent = userAgentString;
2249 _private->userAgentOverridden = userAgentString != nil;
2252 - (NSString *)customUserAgent
2254 if (!_private->userAgentOverridden)
2256 return *_private->userAgent;
2259 - (void)setMediaStyle:(NSString *)mediaStyle
2261 if (_private->mediaStyle != mediaStyle) {
2262 [_private->mediaStyle release];
2263 _private->mediaStyle = [mediaStyle copy];
2267 - (NSString *)mediaStyle
2269 return _private->mediaStyle;
2272 - (BOOL)supportsTextEncoding
2274 id documentView = [[[self mainFrame] frameView] documentView];
2275 return [documentView conformsToProtocol:@protocol(WebDocumentText)]
2276 && [documentView supportsTextEncoding];
2279 - (void)setCustomTextEncodingName:(NSString *)encoding
2281 NSString *oldEncoding = [self customTextEncodingName];
2282 if (encoding == oldEncoding || [encoding isEqualToString:oldEncoding])
2284 FrameLoader* mainFrameLoader = [[self mainFrame] _frameLoader];
2285 if (mainFrameLoader)
2286 mainFrameLoader->reloadAllowingStaleData(encoding);
2289 - (NSString *)_mainFrameOverrideEncoding
2291 WebDataSource *dataSource = [[self mainFrame] provisionalDataSource];
2292 if (dataSource == nil)
2293 dataSource = [[self mainFrame] _dataSource];
2294 if (dataSource == nil)
2296 return nsStringNilIfEmpty([dataSource _documentLoader]->overrideEncoding());
2299 - (NSString *)customTextEncodingName
2301 return [self _mainFrameOverrideEncoding];
2304 - (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script
2306 // Return statements are only valid in a function but some applications pass in scripts
2307 // prefixed with return (<rdar://problems/5103720&4616860>) since older WebKit versions
2308 // silently ignored the return. If the application is linked against an earlier version
2309 // of WebKit we will strip the return so the script wont fail.
2310 if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_JAVASCRIPT_RETURN_QUIRK)) {
2311 NSRange returnStringRange = [script rangeOfString:@"return "];
2312 if (returnStringRange.length && !returnStringRange.location)
2313 script = [script substringFromIndex:returnStringRange.location + returnStringRange.length];
2316 NSString *result = [[[self mainFrame] _bridge] stringByEvaluatingJavaScriptFromString:script];
2317 // The only way stringByEvaluatingJavaScriptFromString can return nil is if the frame was removed by the script
2318 // Since there's no way to get rid of the main frame, result will never ever be nil here.
2324 - (WebScriptObject *)windowScriptObject
2326 Frame* coreFrame = core([self mainFrame]);
2329 return coreFrame->windowScriptObject();
2332 // Get the appropriate user-agent string for a particular URL.
2333 - (NSString *)userAgentForURL:(NSURL *)url
2335 return [self _userAgentForURL:KURL([url absoluteURL])];
2338 - (void)setHostWindow:(NSWindow *)hostWindow
2340 if (!_private->closed && hostWindow != _private->hostWindow) {
2341 [[self mainFrame] _viewWillMoveToHostWindow:hostWindow];
2342 if (_private->hostWindow)
2343 [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowWillCloseNotification object:_private->hostWindow];
2345 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillClose:) name:NSWindowWillCloseNotification object:hostWindow];
2346 [_private->hostWindow release];
2347 _private->hostWindow = [hostWindow retain];
2348 [[self mainFrame] _viewDidMoveToHostWindow];
2352 - (NSWindow *)hostWindow
2354 return _private->hostWindow;
2357 - (NSView <WebDocumentView> *)documentViewAtWindowPoint:(NSPoint)point
2359 return [[self _frameViewAtWindowPoint:point] documentView];
2362 - (NSDictionary *)_elementAtWindowPoint:(NSPoint)windowPoint
2364 WebFrameView *frameView = [self _frameViewAtWindowPoint:windowPoint];
2367 NSView <WebDocumentView> *documentView = [frameView documentView];
2368 if ([documentView conformsToProtocol:@protocol(WebDocumentElement)]) {
2369 NSPoint point = [documentView convertPoint:windowPoint fromView:nil];
2370 return [(NSView <WebDocumentElement> *)documentView elementAtPoint:point];
2372 return [NSDictionary dictionaryWithObject:[frameView webFrame] forKey:WebElementFrameKey];
2375 - (NSDictionary *)elementAtPoint:(NSPoint)point
2377 return [self _elementAtWindowPoint:[self convertPoint:point toView:nil]];
2380 // The following 2 internal NSView methods are called on the drag destination by make scrolling while dragging work.
2381 // Scrolling while dragging will only work if the drag destination is in a scroll view. The WebView is the drag destination.
2382 // When dragging to a WebView, the document subview should scroll, but it doesn't because it is not the drag destination.
2383 // Forward these calls to the document subview to make its scroll view scroll.
2384 - (void)_autoscrollForDraggingInfo:(id)draggingInfo timeDelta:(NSTimeInterval)repeatDelta
2386 NSView <WebDocumentView> *documentView = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
2387 [documentView _autoscrollForDraggingInfo:draggingInfo timeDelta:repeatDelta];
2390 - (BOOL)_shouldAutoscrollForDraggingInfo:(id)draggingInfo
2392 NSView <WebDocumentView> *documentView = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
2393 return [documentView _shouldAutoscrollForDraggingInfo:draggingInfo];
2396 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)draggingInfo
2398 NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
2399 WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]] ? (WebHTMLView*)view : nil);
2400 IntPoint client([draggingInfo draggingLocation]);
2401 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
2402 DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
2403 return core(self)->dragController()->dragEntered(&dragData);
2406 - (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)draggingInfo
2408 NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
2409 WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]] ? (WebHTMLView*)view : nil);
2410 IntPoint client([draggingInfo draggingLocation]);
2411 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
2412 DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
2413 return core(self)->dragController()->dragUpdated(&dragData);
2416 - (void)draggingExited:(id <NSDraggingInfo>)draggingInfo
2418 NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
2419 WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]] ? (WebHTMLView*)view : nil);
2420 IntPoint client([draggingInfo draggingLocation]);
2421 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
2422 DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
2423 core(self)->dragController()->dragExited(&dragData);
2426 - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)draggingInfo
2431 - (BOOL)performDragOperation:(id <NSDraggingInfo>)draggingInfo
2433 NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
2434 WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]]? (WebHTMLView*)view : nil);
2435 IntPoint client([draggingInfo draggingLocation]);
2436 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
2437 DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
2438 return core(self)->dragController()->performDrag(&dragData);
2441 - (NSView *)_hitTest:(NSPoint *)aPoint dragTypes:(NSSet *)types
2443 NSView *hitView = [super _hitTest:aPoint dragTypes:types];
2444 if (!hitView && [[self superview] mouse:*aPoint inRect:[self frame]]) {
2451 - (BOOL)acceptsFirstResponder
2453 return [[[self mainFrame] frameView] acceptsFirstResponder];
2456 - (BOOL)becomeFirstResponder
2458 if (_private->becomingFirstResponder) {
2459 // Fix for unrepro infinite recursion reported in radar 4448181. If we hit this assert on
2460 // a debug build, we should figure out what causes the problem and do a better fix.
2461 ASSERT_NOT_REACHED();
2465 // This works together with setNextKeyView to splice the WebView into
2466 // the key loop similar to the way NSScrollView does this. Note that
2467 // WebFrameView has very similar code.
2468 NSWindow *window = [self window];
2469 WebFrameView *mainFrameView = [[self mainFrame] frameView];
2471 NSResponder *previousFirstResponder = [[self window] _oldFirstResponderBeforeBecoming];
2472 BOOL fromOutside = ![previousFirstResponder isKindOfClass:[NSView class]] || (![(NSView *)previousFirstResponder isDescendantOf:self] && previousFirstResponder != self);
2474 if ([window keyViewSelectionDirection] == NSSelectingPrevious) {
2475 NSView *previousValidKeyView = [self previousValidKeyView];
2476 if ((previousValidKeyView != self) && (previousValidKeyView != mainFrameView)) {
2477 _private->becomingFirstResponder = YES;
2478 _private->becomingFirstResponderFromOutside = fromOutside;
2479 [window makeFirstResponder:previousValidKeyView];
2480 _private->becomingFirstResponderFromOutside = NO;
2481 _private->becomingFirstResponder = NO;
2488 if ([mainFrameView acceptsFirstResponder]) {
2489 _private->becomingFirstResponder = YES;
2490 _private->becomingFirstResponderFromOutside = fromOutside;
2491 [window makeFirstResponder:mainFrameView];
2492 _private->becomingFirstResponderFromOutside = NO;
2493 _private->becomingFirstResponder = NO;
2500 - (NSView *)_webcore_effectiveFirstResponder
2502 WebFrameView *frameView = [[self mainFrame] frameView];
2503 return frameView ? [frameView _webcore_effectiveFirstResponder] : [super _webcore_effectiveFirstResponder];
2506 - (void)setNextKeyView:(NSView *)aView
2508 // This works together with becomeFirstResponder to splice the WebView into
2509 // the key loop similar to the way NSScrollView does this. Note that
2510 // WebFrameView has very similar code.
2511 WebFrameView *mainFrameView = [[self mainFrame] frameView];
2512 if (mainFrameView != nil) {
2513 [mainFrameView setNextKeyView:aView];
2515 [super setNextKeyView:aView];
2519 static WebFrame *incrementFrame(WebFrame *curr, BOOL forward, BOOL wrapFlag)
2521 Frame* coreFrame = core(curr);
2523 ? coreFrame->tree()->traverseNextWithWrap(wrapFlag)
2524 : coreFrame->tree()->traversePreviousWithWrap(wrapFlag));
2527 - (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag
2529 return [self searchFor:string direction:forward caseSensitive:caseFlag wrap:wrapFlag startInSelection:NO];
2532 + (void)registerViewClass:(Class)viewClass representationClass:(Class)representationClass forMIMEType:(NSString *)MIMEType
2534 [[WebFrameView _viewTypesAllowImageTypeOmission:YES] setObject:viewClass forKey:MIMEType];
2535 [[WebDataSource _repTypesAllowImageTypeOmission:YES] setObject:representationClass forKey:MIMEType];
2537 // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
2538 // in the WebCore MIMEType registry. For now we're doing this in a safe, limited manner
2539 // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
2540 if ([viewClass class] == [WebHTMLView class])
2541 MIMETypeRegistry::getSupportedNonImageMIMETypes().add(MIMEType);
2544 - (void)setGroupName:(NSString *)groupName
2546 if (!_private->page)
2548 _private->page->setGroupName(groupName);
2551 - (NSString *)groupName
2553 if (!_private->page)
2555 return _private->page->groupName();
2558 - (double)estimatedProgress
2560 if (!_private->page)
2563 return _private->page->progress()->estimatedProgress();
2566 - (NSArray *)pasteboardTypesForSelection
2568 NSView <WebDocumentView> *documentView = [[[self _selectedOrMainFrame] frameView] documentView];
2569 if ([documentView conformsToProtocol:@protocol(WebDocumentSelection)]) {
2570 return [(NSView <WebDocumentSelection> *)documentView pasteboardTypesForSelection];
2572 return [NSArray array];
2575 - (void)writeSelectionWithPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
2577 WebFrame *frame = [self _selectedOrMainFrame];
2578 if (frame && [frame _hasSelection]) {
2579 NSView <WebDocumentView> *documentView = [[frame frameView] documentView];
2580 if ([documentView conformsToProtocol:@protocol(WebDocumentSelection)])
2581 [(NSView <WebDocumentSelection> *)documentView writeSelectionWithPasteboardTypes:types toPasteboard:pasteboard];
2585 - (NSArray *)pasteboardTypesForElement:(NSDictionary *)element
2587 if ([element objectForKey:WebElementImageURLKey] != nil) {
2588 return [NSPasteboard _web_writableTypesForImageIncludingArchive:([element objectForKey:WebElementDOMNodeKey] != nil)];
2589 } else if ([element objectForKey:WebElementLinkURLKey] != nil) {
2590 return [NSPasteboard _web_writableTypesForURL];
2591 } else if ([[element objectForKey:WebElementIsSelectedKey] boolValue]) {
2592 return [self pasteboardTypesForSelection];
2594 return [NSArray array];
2597 - (void)writeElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
2599 if ([element objectForKey:WebElementImageURLKey] != nil) {
2600 [self _writeImageForElement:element withPasteboardTypes:types toPasteboard:pasteboard];
2601 } else if ([element objectForKey:WebElementLinkURLKey] != nil) {
2602 [self _writeLinkElement:element withPasteboardTypes:types toPasteboard:pasteboard];
2603 } else if ([[element objectForKey:WebElementIsSelectedKey] boolValue]) {
2604 [self writeSelectionWithPasteboardTypes:types toPasteboard:pasteboard];
2608 - (void)moveDragCaretToPoint:(NSPoint)point
2610 if (Page* page = core(self))
2611 page->dragController()->placeDragCaret(IntPoint([self convertPoint:point toView:nil]));
2614 - (void)removeDragCaret
2616 if (Page* page = core(self))
2617 page->dragController()->dragEnded();
2620 - (void)setMainFrameURL:(NSString *)URLString
2622 [[self mainFrame] loadRequest: [NSURLRequest requestWithURL: [NSURL _web_URLWithDataAsString: URLString]]];
2625 - (NSString *)mainFrameURL
2628 ds = [[self mainFrame] provisionalDataSource];
2630 ds = [[self mainFrame] _dataSource];
2631 return [[[ds request] URL] _web_originalDataAsString];
2636 LOG (Bindings, "isLoading = %d", (int)[self _isLoading]);
2637 return [self _isLoading];
2640 - (NSString *)mainFrameTitle
2642 NSString *mainFrameTitle = [[[self mainFrame] _dataSource] pageTitle];
2643 return (mainFrameTitle != nil) ? mainFrameTitle : (NSString *)@"";
2646 - (NSImage *)mainFrameIcon
2648 return [[WebIconDatabase sharedIconDatabase] iconForURL:[[[[self mainFrame] _dataSource] _URL] _web_originalDataAsString] withSize:WebIconSmallSize];
2651 - (DOMDocument *)mainFrameDocument
2653 // only return the actual value if the state we're in gives NSTreeController
2654 // enough time to release its observers on the old model
2655 if (_private->mainFrameDocumentReady)
2656 return [[self mainFrame] DOMDocument];
2660 - (void)setDrawsBackground:(BOOL)drawsBackground
2662 if (_private->drawsBackground == drawsBackground)
2664 _private->drawsBackground = drawsBackground;
2665 [[self mainFrame] _updateBackground];
2668 - (BOOL)drawsBackground
2670 return _private->drawsBackground;
2675 @implementation WebView (WebIBActions)
2677 - (IBAction)takeStringURLFrom: sender
2679 NSString *URLString = [sender stringValue];
2681 [[self mainFrame] loadRequest: [NSURLRequest requestWithURL: [NSURL _web_URLWithDataAsString: URLString]]];
2686 if (!_private->page)
2689 return !!_private->page->backForwardList()->backItem();
2692 - (BOOL)canGoForward
2694 if (!_private->page)
2697 return !!_private->page->backForwardList()->forwardItem();
2700 - (IBAction)goBack:(id)sender
2705 - (IBAction)goForward:(id)sender
2710 - (IBAction)stopLoading:(id)sender
2712 [[self mainFrame] stopLoading];
2715 - (IBAction)reload:(id)sender
2717 [[self mainFrame] reload];
2720 #define MinimumTextSizeMultiplier 0.5f
2721 #define MaximumTextSizeMultiplier 3.0f
2722 #define TextSizeMultiplierRatio 1.2f
2724 - (BOOL)canMakeTextSmaller
2726 BOOL canShrinkMore = _private->textSizeMultiplier/TextSizeMultiplierRatio > MinimumTextSizeMultiplier;
2727 return [self _performTextSizingSelector:(SEL)0 withObject:nil onTrackingDocs:canShrinkMore selForNonTrackingDocs:@selector(_canMakeTextSmaller) newScaleFactor:0];
2730 - (BOOL)canMakeTextLarger
2732 BOOL canGrowMore = _private->textSizeMultiplier*TextSizeMultiplierRatio < MaximumTextSizeMultiplier;
2733 return [self _performTextSizingSelector:(SEL)0 withObject:nil onTrackingDocs:canGrowMore selForNonTrackingDocs:@selector(_canMakeTextLarger) newScaleFactor:0];
2736 - (IBAction)makeTextSmaller:(id)sender
2738 float newScale = _private->textSizeMultiplier / TextSizeMultiplierRatio;
2739 BOOL canShrinkMore = newScale > MinimumTextSizeMultiplier;
2740 [self _performTextSizingSelector:@selector(_makeTextSmaller:) withObject:sender onTrackingDocs:canShrinkMore selForNonTrackingDocs:@selector(_canMakeTextSmaller) newScaleFactor:newScale];
2743 - (IBAction)makeTextLarger:(id)sender
2745 float newScale = _private->textSizeMultiplier*TextSizeMultiplierRatio;
2746 BOOL canGrowMore = newScale < MaximumTextSizeMultiplier;
2747 [self _performTextSizingSelector:@selector(_makeTextLarger:) withObject:sender onTrackingDocs:canGrowMore selForNonTrackingDocs:@selector(_canMakeTextLarger) newScaleFactor:newScale];
2750 - (IBAction)toggleSmartInsertDelete:(id)sender
2752 [self setSmartInsertDeleteEnabled:![self smartInsertDeleteEnabled]];
2755 - (IBAction)toggleContinuousSpellChecking:(id)sender
2757 [self setContinuousSpellCheckingEnabled:![self isContinuousSpellCheckingEnabled]];
2760 - (BOOL)_responderValidateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item
2762 id responder = [self _responderForResponderOperations];
2763 if (responder != self && [responder respondsToSelector:[item action]]) {
2764 if ([responder respondsToSelector:@selector(validateUserInterfaceItemWithoutDelegate:)])
2765 return [responder validateUserInterfaceItemWithoutDelegate:item];
2766 if ([responder respondsToSelector:@selector(validateUserInterfaceItem:)])
2767 return [responder validateUserInterfaceItem:item];
2773 - (BOOL)canMakeTextStandardSize
2775 BOOL notAlreadyStandard = _private->textSizeMultiplier != 1.0f;
2776 return [self _performTextSizingSelector:(SEL)0 withObject:nil onTrackingDocs:notAlreadyStandard selForNonTrackingDocs:@selector(_canMakeTextStandardSize) newScaleFactor:0.0f];
2779 - (IBAction)makeTextStandardSize:(id)sender
2781 BOOL notAlreadyStandard = _private->textSizeMultiplier != 1.0f;
2782 [self _performTextSizingSelector:@selector(_makeTextStandardSize:) withObject:sender onTrackingDocs:notAlreadyStandard selForNonTrackingDocs:@selector(_canMakeTextStandardSize) newScaleFactor:1.0f];
2785 #define VALIDATE(name) \
2786 else if (action == @selector(name:)) { return [self _responderValidateUserInterfaceItem:item]; }
2788 - (BOOL)validateUserInterfaceItemWithoutDelegate:(id <NSValidatedUserInterfaceItem>)item
2790 SEL action = [item action];
2792 if (action == @selector(goBack:)) {
2793 return [self canGoBack];
2794 } else if (action == @selector(goForward:)) {
2795 return [self canGoForward];
2796 } else if (action == @selector(makeTextLarger:)) {
2797 return [self canMakeTextLarger];
2798 } else if (action == @selector(makeTextSmaller:)) {
2799 return [self canMakeTextSmaller];
2800 } else if (action == @selector(makeTextStandardSize:)) {
2801 return [self canMakeTextStandardSize];
2802 } else if (action == @selector(reload:)) {
2803 return [[self mainFrame] _dataSource] != nil;
2804 } else if (action == @selector(stopLoading:)) {
2805 return [self _isLoading];
2806 } else if (action == @selector(toggleContinuousSpellChecking:)) {
2807 BOOL checkMark = NO;
2809 if ([self _continuousCheckingAllowed]) {
2810 checkMark = [self isContinuousSpellCheckingEnabled];
2813 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
2814 NSMenuItem *menuItem = (NSMenuItem *)item;
2815 [menuItem setState:checkMark ? NSOnState : NSOffState];
2818 #ifndef BUILDING_ON_TIGER
2819 } else if (action == @selector(toggleGrammarChecking:)) {
2820 BOOL checkMark = [self isGrammarCheckingEnabled];
2821 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
2822 NSMenuItem *menuItem = (NSMenuItem *)item;
2823 [menuItem setState:checkMark ? NSOnState : NSOffState];
2828 FOR_EACH_RESPONDER_SELECTOR(VALIDATE)
2833 - (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item
2835 BOOL result = [self validateUserInterfaceItemWithoutDelegate:item];
2836 return CallUIDelegateReturningBoolean(result, self, @selector(webView:validateUserInterfaceItem:defaultValidation:), item, result);
2841 @implementation WebView (WebPendingPublic)
2843 - (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag startInSelection:(BOOL)startInSelection
2845 if (_private->closed)
2848 // Get the frame holding the selection, or start with the main frame
2849 WebFrame *startFrame = [self _selectedOrMainFrame];
2851 // Search the first frame, then all the other frames, in order
2852 NSView <WebDocumentSearching> *startSearchView = nil;
2853 WebFrame *frame = startFrame;
2855 WebFrame *nextFrame = incrementFrame(frame, forward, wrapFlag);
2857 BOOL onlyOneFrame = (frame == nextFrame);
2858 ASSERT(!onlyOneFrame || frame == startFrame);
2860 id <WebDocumentView> view = [[frame frameView] documentView];
2861 if ([view conformsToProtocol:@protocol(WebDocumentSearching)]) {
2862 NSView <WebDocumentSearching> *searchView = (NSView <WebDocumentSearching> *)view;
2864 if (frame == startFrame)
2865 startSearchView = searchView;
2868 // In some cases we have to search some content twice; see comment later in this method.
2869 // We can avoid ever doing this in the common one-frame case by passing YES for wrapFlag
2870 // here, and then bailing out before we get to the code that would search again in the
2872 BOOL wrapOnThisPass = wrapFlag && onlyOneFrame;
2873 if ([searchView conformsToProtocol:@protocol(WebDocumentIncrementalSearching)])
2874 foundString = [(NSView <WebDocumentIncrementalSearching> *)searchView searchFor:string direction:forward caseSensitive:caseFlag wrap:wrapOnThisPass startInSelection:startInSelection];
2876 foundString = [searchView searchFor:string direction:forward caseSensitive:caseFlag wrap:wrapOnThisPass];
2879 if (frame != startFrame)
2880 [startFrame _clearSelection];
2881 [[self window] makeFirstResponder:searchView];
2889 } while (frame && frame != startFrame);
2891 // If there are multiple frames and wrapFlag is true and we've visited each one without finding a result, we still need to search in the
2892 // first-searched frame up to the selection. However, the API doesn't provide a way to search only up to a particular point. The only
2893 // way to make sure the entire frame is searched is to pass YES for the wrapFlag. When there are no matches, this will search again
2894 // some content that we already searched on the first pass. In the worst case, we could search the entire contents of this frame twice.
2895 // To fix this, we'd need to add a mechanism to specify a range in which to search.
2896 if (wrapFlag && startSearchView) {
2898 if ([startSearchView conformsToProtocol:@protocol(WebDocumentIncrementalSearching)])
2899 foundString = [(NSView <WebDocumentIncrementalSearching> *)startSearchView searchFor:string direction:forward caseSensitive:caseFlag wrap:YES startInSelection:startInSelection];
2901 foundString = [startSearchView searchFor:string direction:forward caseSensitive:caseFlag wrap:YES];
2903 [[self window] makeFirstResponder:startSearchView];
2910 - (void)setHoverFeedbackSuspended:(BOOL)newValue
2912 if (_private->hoverFeedbackSuspended == newValue)
2915 _private->hoverFeedbackSuspended = newValue;
2916 id <WebDocumentView> documentView = [[[self mainFrame] frameView] documentView];
2917 // FIXME: in a perfect world we'd do this in a general way that worked with any document view,
2918 // such as by calling a protocol method or using respondsToSelector or sending a notification.
2919 // But until there is any need for these more general solutions, we'll just hardwire it to work
2920 // with WebHTMLView.
2921 // Note that _hoverFeedbackSuspendedChanged needs to be called only on the main WebHTMLView, not
2922 // on each subframe separately.
2923 if ([documentView isKindOfClass:[WebHTMLView class]])
2924 [(WebHTMLView *)documentView _hoverFeedbackSuspendedChanged];
2927 - (BOOL)isHoverFeedbackSuspended
2929 return _private->hoverFeedbackSuspended;
2932 - (void)setMainFrameDocumentReady:(BOOL)mainFrameDocumentReady
2934 // by setting this to NO, calls to mainFrameDocument are forced to return nil
2935 // setting this to YES lets it return the actual DOMDocument value
2936 // we use this to tell NSTreeController to reset its observers and clear its state
2937 if (_private->mainFrameDocumentReady == mainFrameDocumentReady)
2939 [self _willChangeValueForKey:_WebMainFrameDocumentKey];
2940 _private->mainFrameDocumentReady = mainFrameDocumentReady;
2941 [self _didChangeValueForKey:_WebMainFrameDocumentKey];
2942 // this will cause observers to call mainFrameDocument where this flag will be checked
2945 // This method name is used by Mail on Tiger (but not post-Tiger), so we shouldn't delete it
2946 // until the day comes when we're no longer supporting Mail on Tiger.
2947 - (WebFrame *)_frameForCurrentSelection
2949 return [self _selectedOrMainFrame];
2952 - (void)setTabKeyCyclesThroughElements:(BOOL)cyclesElements
2954 _private->tabKeyCyclesThroughElementsChanged = YES;
2956 _private->page->setTabKeyCyclesThroughElements(cyclesElements);
2959 - (BOOL)tabKeyCyclesThroughElements
2961 return _private->page && _private->page->tabKeyCyclesThroughElements();
2964 - (void)setScriptDebugDelegate:(id)delegate
2966 _private->scriptDebugDelegate = delegate;
2967 [_private->scriptDebugDelegateForwarder release];
2968 _private->scriptDebugDelegateForwarder = nil;
2970 [self _attachScriptDebuggerToAllFrames];
2972 [self _detachScriptDebuggerFromAllFrames];
2975 - (id)scriptDebugDelegate
2977 return _private->scriptDebugDelegate;
2982 Frame* coreFrame = core([self mainFrame]);
2985 return coreFrame->shouldClose();
2988 - (NSAppleEventDescriptor *)aeDescByEvaluatingJavaScriptFromString:(NSString *)script
2990 return [[[self mainFrame] _bridge] aeDescByEvaluatingJavaScriptFromString:script];
2993 - (BOOL)canMarkAllTextMatches
2995 WebFrame *frame = [self mainFrame];
2997 id <WebDocumentView> view = [[frame frameView] documentView];
2998 if (view && ![view conformsToProtocol:@protocol(WebMultipleTextMatches)])
3001 frame = incrementFrame(frame, YES, NO);
3007 - (NSUInteger)markAllMatchesForText:(NSString *)string caseSensitive:(BOOL)caseFlag highlight:(BOOL)highlight limit:(NSUInteger)limit
3009 WebFrame *frame = [self mainFrame];
3010 unsigned matchCount = 0;
3012 id <WebDocumentView> view = [[frame frameView] documentView];
3013 if ([view conformsToProtocol:@protocol(WebMultipleTextMatches)]) {
3014 [(NSView <WebMultipleTextMatches>*)view setMarkedTextMatchesAreHighlighted:highlight];
3016 ASSERT(limit == 0 || matchCount < limit);
3017 matchCount += [(NSView <WebMultipleTextMatches>*)view markAllMatchesForText:string caseSensitive:caseFlag limit:limit == 0 ? 0 : limit - matchCount];
3019 // Stop looking if we've reached the limit. A limit of 0 means no limit.
3020 if (limit > 0 && matchCount >= limit)
3024 frame = incrementFrame(frame, YES, NO);
3030 - (void)unmarkAllTextMatches
3032 WebFrame *frame = [self mainFrame];
3034 id <WebDocumentView> view = [[frame frameView] documentView];
3035 if ([view conformsToProtocol:@protocol(WebMultipleTextMatches)])
3036 [(NSView <WebMultipleTextMatches>*)view unmarkAllTextMatches];
3038 frame = incrementFrame(frame, YES, NO);
3042 - (NSArray *)rectsForTextMatches
3044 NSMutableArray *result = [NSMutableArray array];
3045 WebFrame *frame = [self mainFrame];
3047 id <WebDocumentView> view = [[frame frameView] documentView];
3048 if ([view conformsToProtocol:@protocol(WebMultipleTextMatches)]) {
3049 NSView <WebMultipleTextMatches> *documentView = (NSView <WebMultipleTextMatches> *)view;
3050 NSRect documentViewVisibleRect = [documentView visibleRect];
3051 NSArray *originalRects = [documentView rectsForTextMatches];
3052 unsigned rectCount = [originalRects count];
3054 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
3055 for (rectIndex = 0; rectIndex < rectCount; ++rectIndex) {
3056 NSRect r = [[originalRects objectAtIndex:rectIndex] rectValue];
3057 // Clip rect to document view's visible rect so rect is confined to subframe
3058 r = NSIntersectionRect(r, documentViewVisibleRect);
3059 if (NSIsEmptyRect(r))
3062 // Convert rect to our coordinate system
3063 r = [documentView convertRect:r toView:self];
3064 [result addObject:[NSValue valueWithRect:r]];
3065 if (rectIndex % 10 == 0) {
3067 pool = [[NSAutoreleasePool alloc] init];
3073 frame = incrementFrame(frame, YES, NO);
3079 - (void)scrollDOMRangeToVisible:(DOMRange *)range
3081 [[[range startContainer] _bridge] scrollDOMRangeToVisible:range];
3086 return _private->allowsUndo;
3089 - (void)setAllowsUndo:(BOOL)flag
3091 _private->allowsUndo = flag;
3096 @implementation WebView (WebViewPrintingPrivate)
3098 - (float)_headerHeight
3100 return CallUIDelegateReturningFloat(self, @selector(webViewHeaderHeight:));
3103 - (float)_footerHeight
3105 return CallUIDelegateReturningFloat(self, @selector(webViewFooterHeight:));
3108 - (void)_drawHeaderInRect:(NSRect)rect
3110 #ifdef DEBUG_HEADER_AND_FOOTER
3111 NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
3112 [currentContext saveGraphicsState];
3113 [[NSColor yellowColor] set];
3115 [currentContext restoreGraphicsState];
3118 SEL selector = @selector(webView:drawHeaderInRect:);
3119 if (![_private->UIDelegate respondsToSelector:selector])
3122 NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
3123 [currentContext saveGraphicsState];
3126 CallUIDelegate(self, selector, rect);
3128 [currentContext restoreGraphicsState];
3131 - (void)_drawFooterInRect:(NSRect)rect
3133 #ifdef DEBUG_HEADER_AND_FOOTER
3134 NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
3135 [currentContext saveGraphicsState];
3136 [[NSColor cyanColor] set];
3138 [currentContext restoreGraphicsState];
3141 SEL selector = @selector(webView:drawFooterInRect:);
3142 if (![_private->UIDelegate respondsToSelector:selector])
3145 NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
3146 [currentContext saveGraphicsState];
3149 CallUIDelegate(self, selector, rect);
3151 [currentContext restoreGraphicsState];
3154 - (void)_adjustPrintingMarginsForHeaderAndFooter
3156 NSPrintOperation *op = [NSPrintOperation currentOperation];
3157 NSPrintInfo *info = [op printInfo];
3158 NSMutableDictionary *infoDictionary = [info dictionary];
3160 // We need to modify the top and bottom margins in the NSPrintInfo to account for the space needed by the
3161 // header and footer. Because this method can be called more than once on the same NSPrintInfo (see 5038087),
3162 // we stash away the unmodified top and bottom margins the first time this method is called, and we read from
3163 // those stashed-away values on subsequent calls.
3164 float originalTopMargin;
3165 float originalBottomMargin;
3166 NSNumber *originalTopMarginNumber = [infoDictionary objectForKey:WebKitOriginalTopPrintingMarginKey];
3167 if (!originalTopMarginNumber) {
3168 ASSERT(![infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey]);
3169 originalTopMargin = [info topMargin];
3170 originalBottomMargin = [info bottomMargin];
3171 [infoDictionary setObject:[NSNumber numberWithFloat:originalTopMargin] forKey:WebKitOriginalTopPrintingMarginKey];
3172 [infoDictionary setObject:[NSNumber numberWithFloat:originalBottomMargin] forKey:WebKitOriginalBottomPrintingMarginKey];
3174 ASSERT([originalTopMarginNumber isKindOfClass:[NSNumber class]]);
3175 ASSERT([[infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey] isKindOfClass:[NSNumber class]]);
3176 originalTopMargin = [originalTopMarginNumber floatValue];
3177 originalBottomMargin = [[infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey] floatValue];
3180 float scale = [op _web_pageSetupScaleFactor];
3181 [info setTopMargin:originalTopMargin + [self _headerHeight] * scale];
3182 [info setBottomMargin:originalBottomMargin + [self _footerHeight] * scale];
3185 - (void)_drawHeaderAndFooter
3187 // The header and footer rect height scales with the page, but the width is always
3188 // all the way across the printed page (inset by printing margins).
3189 NSPrintOperation *op = [NSPrintOperation currentOperation];
3190 float scale = [op _web_pageSetupScaleFactor];
3191 NSPrintInfo *printInfo = [op printInfo];
3192 NSSize paperSize = [printInfo paperSize];
3193 float headerFooterLeft = [printInfo leftMargin]/scale;
3194 float headerFooterWidth = (paperSize.width - ([printInfo leftMargin] + [printInfo rightMargin]))/scale;
3195 NSRect footerRect = NSMakeRect(headerFooterLeft, [printInfo bottomMargin]/scale - [self _footerHeight] ,
3196 headerFooterWidth, [self _footerHeight]);
3197 NSRect headerRect = NSMakeRect(headerFooterLeft, (paperSize.height - [printInfo topMargin])/scale,
3198 headerFooterWidth, [self _headerHeight]);
3200 [self _drawHeaderInRect:headerRect];
3201 [self _drawFooterInRect:footerRect];
3205 @implementation WebView (WebDebugBinding)
3207 - (void)addObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context
3209 LOG (Bindings, "addObserver:%p forKeyPath:%@ options:%x context:%p", anObserver, keyPath, options, context);
3210 [super addObserver:anObserver forKeyPath:keyPath options:options context:context];
3213 - (void)removeObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath
3215 LOG (Bindings, "removeObserver:%p forKeyPath:%@", anObserver, keyPath);
3216 [super removeObserver:anObserver forKeyPath:keyPath];
3221 //==========================================================================================
3224 @implementation WebView (WebViewCSS)
3226 - (DOMCSSStyleDeclaration *)computedStyleForElement:(DOMElement *)element pseudoElement:(NSString *)pseudoElement
3228 // FIXME: is this the best level for this conversion?
3229 if (pseudoElement == nil)
3230 pseudoElement = @"";
3232 return [[element ownerDocument] getComputedStyle:element pseudoElement:pseudoElement];
3237 @implementation WebView (WebViewEditing)
3239 - (DOMRange *)editableDOMRangeForPoint:(NSPoint)point
3241 Page* page = core(self);
3244 return kit(page->mainFrame()->editor()->rangeForPoint(IntPoint([self convertPoint:point toView:nil])).get());
3247 - (BOOL)_shouldChangeSelectedDOMRange:(DOMRange *)currentRange toDOMRange:(DOMRange *)proposedRange affinity:(NSSelectionAffinity)selectionAffinity stillSelecting:(BOOL)flag;
3249 // FIXME: This quirk is needed due to <rdar://problem/4985321> - We can phase it out once Aperture can adopt the new behavior on their end
3250 if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_APERTURE_QUIRK) && [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.Aperture"])
3252 return [[self _editingDelegateForwarder] webView:self shouldChangeSelectedDOMRange:currentRange toDOMRange:proposedRange affinity:selectionAffinity stillSelecting:flag];
3255 - (BOOL)maintainsInactiveSelection
3260 - (void)setSelectedDOMRange:(DOMRange *)range affinity:(NSSelectionAffinity)selectionAffinity
3262 Frame* coreFrame = core([self _selectedOrMainFrame]);
3267 coreFrame->selectionController()->clear();
3269 // Derive the frame to use from the range passed in.
3270 // Using _bridgeForSelectedOrMainFrame could give us a different document than
3271 // the one the range uses.
3272 coreFrame = core([range startContainer])->document()->frame();
3276 coreFrame->selectionController()->setSelectedRange([range _range], core(selectionAffinity), true);
3280 - (DOMRange *)selectedDOMRange
3282 Frame* coreFrame = core([self _selectedOrMainFrame]);
3285 return kit(coreFrame->selectionController()->toRange().get());
3288 - (NSSelectionAffinity)selectionAffinity
3290 Frame* coreFrame = core([self _selectedOrMainFrame]);
3292 return NSSelectionAffinityDownstream;
3293 return kit(coreFrame->selectionController()->affinity());
3296 - (void)setEditable:(BOOL)flag
3298 if (_private->editable != flag) {
3299 _private->editable = flag;
3300 if (!_private->tabKeyCyclesThroughElementsChanged && _private->page)
3301 _private->page->setTabKeyCyclesThroughElements(!flag);
3302 Frame* mainFrame = [[[self mainFrame] _bridge] _frame];
3305 mainFrame->applyEditingStyleToBodyElement();
3306 // If the WebView is made editable and the selection is empty, set it to something.
3307 if (![self selectedDOMRange])
3308 mainFrame->setSelectionFromNone();
3310 mainFrame->removeEditingStyleFromBodyElement();
3317 return _private->editable;
3320 - (void)setTypingStyle:(DOMCSSStyleDeclaration *)style
3322 // We don't know enough at thls level to pass in a relevant WebUndoAction; we'd have to
3323 // change the API to allow this.
3324 [[self _bridgeForSelectedOrMainFrame] setTypingStyle:style withUndoAction:EditActionUnspecified];
3327 - (DOMCSSStyleDeclaration *)typingStyle
3329 return [[self _bridgeForSelectedOrMainFrame] typingStyle];
3332 - (void)setSmartInsertDeleteEnabled:(BOOL)flag
3334 _private->smartInsertDeleteEnabled = flag;
3337 - (BOOL)smartInsertDeleteEnabled
3339 return _private->smartInsertDeleteEnabled;
3342 - (void)setContinuousSpellCheckingEnabled:(BOOL)flag
3344 if (continuousSpellCheckingEnabled != flag) {
3345 continuousSpellCheckingEnabled = flag;
3346 [[NSUserDefaults standardUserDefaults] setBool:continuousSpellCheckingEnabled forKey:WebContinuousSpellCheckingEnabled];
3349 if ([self isContinuousSpellCheckingEnabled]) {
3350 [[self class] _preflightSpellChecker];
3352 [[self mainFrame] _unmarkAllMisspellings];
3356 - (BOOL)isContinuousSpellCheckingEnabled
3358 return (continuousSpellCheckingEnabled && [self _continuousCheckingAllowed]);
3361 - (NSInteger)spellCheckerDocumentTag
3363 if (!_private->hasSpellCheckerDocumentTag) {
3364 _private->spellCheckerDocumentTag = [NSSpellChecker uniqueSpellDocumentTag];
3365 _private->hasSpellCheckerDocumentTag = YES;
3367 return _private->spellCheckerDocumentTag;
3370 - (NSUndoManager *)undoManager
3372 if (!_private->allowsUndo)
3375 NSUndoManager *undoManager = [[self _editingDelegateForwarder] undoManagerForWebView:self];
3379 return [super undoManager];
3382 - (void)registerForEditingDelegateNotification:(NSString *)name selector:(SEL)selector
3384 NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
3385 if ([_private->editingDelegate respondsToSelector:selector])
3386 [defaultCenter addObserver:_private->editingDelegate selector:selector name:name object:self];
3389 - (void)setEditingDelegate:(id)delegate
3391 if (_private->editingDelegate == delegate)
3394 NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
3396 // remove notifications from current delegate
3397 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidBeginEditingNotification object:self];
3398 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidChangeNotification object:self];
3399 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidEndEditingNotification object:self];
3400 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidChangeTypingStyleNotification object:self];
3401 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidChangeSelectionNotification object:self];
3403 _private->editingDelegate = delegate;
3404 [_private->editingDelegateForwarder release];
3405 _private->editingDelegateForwarder = nil;
3407 // add notifications for new delegate
3408 [self registerForEditingDelegateNotification:WebViewDidBeginEditingNotification selector:@selector(webViewDidBeginEditing:)];
3409 [self registerForEditingDelegateNotification:WebViewDidChangeNotification selector:@selector(webViewDidChange:)];
3410 [self registerForEditingDelegateNotification:WebViewDidEndEditingNotification selector:@selector(webViewDidEndEditing:)];
3411 [self registerForEditingDelegateNotification:WebViewDidChangeTypingStyleNotification selector:@selector(webViewDidChangeTypingStyle:)];
3412 [self registerForEditingDelegateNotification:WebViewDidChangeSelectionNotification selector:@selector(webViewDidChangeSelection:)];
3415 - (id)editingDelegate
3417 return _private->editingDelegate;
3420 - (DOMCSSStyleDeclaration *)styleDeclarationWithText:(NSString *)text
3422 // FIXME: Should this really be attached to the document with the current selection?
3423 DOMCSSStyleDeclaration *decl = [[[self _selectedOrMainFrame] DOMDocument] createCSSStyleDeclaration];
3424 [decl setCssText:text];
3430 @implementation WebView (WebViewGrammarChecking)
3432 // FIXME: This method should be merged into WebViewEditing when we're not in API freeze
3433 - (BOOL)isGrammarCheckingEnabled
3435 #ifdef BUILDING_ON_TIGER
3438 return grammarCheckingEnabled;
3442 #ifndef BUILDING_ON_TIGER
3443 // FIXME: This method should be merged into WebViewEditing when we're not in API freeze
3444 - (void)setGrammarCheckingEnabled:(BOOL)flag
3446 if (grammarCheckingEnabled == flag)
3449 grammarCheckingEnabled = flag;
3450 [[NSUserDefaults standardUserDefaults] setBool:grammarCheckingEnabled forKey:WebGrammarCheckingEnabled];
3452 // FIXME 4811447: workaround for lack of API
3453 NSSpellChecker *spellChecker = [NSSpellChecker sharedSpellChecker];
3454 if ([spellChecker respondsToSelector:@selector(_updateGrammar)])
3455 [spellChecker performSelector:@selector(_updateGrammar)];
3457 // We call _preflightSpellChecker when turning continuous spell checking on, but we don't need to do that here
3458 // because grammar checking only occurs on code paths that already preflight spell checking appropriately.
3460 if (![self isGrammarCheckingEnabled])
3461 [[self mainFrame] _unmarkAllBadGrammar];
3464 // FIXME: This method should be merged into WebIBActions when we're not in API freeze
3465 - (void)toggleGrammarChecking:(id)sender
3467 [self setGrammarCheckingEnabled:![self isGrammarCheckingEnabled]];
3473 @implementation WebView (WebViewUndoableEditing)
3475 - (void)replaceSelectionWithNode:(DOMNode *)node
3477 [[self _bridgeForSelectedOrMainFrame] replaceSelectionWithNode:node selectReplacement:YES smartReplace:NO matchStyle:NO];
3480 - (void)replaceSelectionWithText:(NSString *)text
3482 [[self _bridgeForSelectedOrMainFrame] replaceSelectionWithText:text selectReplacement:YES smartReplace:NO];
3485 - (void)replaceSelectionWithMarkupString:(NSString *)markupString
3487 [[self _bridgeForSelectedOrMainFrame] replaceSelectionWithMarkupString:markupString baseURLString:nil selectReplacement:YES smartReplace:NO];
3490 - (void)replaceSelectionWithArchive:(WebArchive *)archive
3492 [[[[self _bridgeForSelectedOrMainFrame] webFrame] _dataSource] _replaceSelectionWithArchive:archive selectReplacement:YES];
3495 - (void)deleteSelection
3497 WebFrame *webFrame = [self _selectedOrMainFrame];
3498 Frame* coreFrame = core(webFrame);
3500 coreFrame->editor()->deleteSelectionWithSmartDelete([(WebHTMLView *)[[webFrame frameView] documentView] _canSmartCopyOrDelete]);
3503 - (void)applyStyle:(DOMCSSStyleDeclaration *)style
3505 // We don't know enough at thls level to pass in a relevant WebUndoAction; we'd have to
3506 // change the API to allow this.
3507 WebFrame *webFrame = [self _selectedOrMainFrame];
3508 Frame* coreFrame = core(webFrame);
3510 coreFrame->editor()->applyStyle(core(style));
3515 @implementation WebView (WebViewEditingActions)
3517 - (void)_performResponderOperation:(SEL)selector with:(id)parameter
3519 static BOOL reentered = NO;
3521 [[self nextResponder] tryToPerform:selector with:parameter];
3525 // There are two possibilities here.
3527 // One is that WebView has been called in its role as part of the responder chain.
3528 // In that case, it's fine to call the first responder and end up calling down the
3529 // responder chain again. Later we will return here with reentered = YES and continue
3530 // past the WebView.
3532 // The other is that we are being called directly, in which case we want to pass the
3533 // selector down to the view inside us that can handle it, and continue down the
3534 // responder chain as usual.
3536 // Pass this selector down to the first responder.
3537 NSResponder *responder = [self _responderForResponderOperations];
3539 [responder tryToPerform:selector with:parameter];
3543 #define FORWARD(name) \
3544 - (void)name:(id)sender { [self _performResponderOperation:_cmd with:sender]; }
3546 FOR_EACH_RESPONDER_SELECTOR(FORWARD)
3548 - (void)insertText:(NSString *)text
3550 [self _performResponderOperation:_cmd with:text];
3555 @implementation WebView (WebViewEditingInMail)
3557 - (void)_insertNewlineInQuotedContent;
3559 [[self _bridgeForSelectedOrMainFrame] insertParagraphSeparatorInQuotedContent];
3562 - (void)_replaceSelectionWithNode:(DOMNode *)node matchStyle:(BOOL)matchStyle
3564 [[self _bridgeForSelectedOrMainFrame] replaceSelectionWithNode:node selectReplacement:YES smartReplace:NO matchStyle:matchStyle];
3569 static WebFrameView *containingFrameView(NSView *view)
3571 while (view && ![view isKindOfClass:[WebFrameView class]])
3572 view = [view superview];
3573 return (WebFrameView *)view;
3576 @implementation WebView (WebFileInternal)
3578 + (void)_setCacheModel:(WebCacheModel)cacheModel
3580 if (s_didSetCacheModel && cacheModel == s_cacheModel)
3583 NSString *nsurlCacheDirectory = [(NSString *)WKCopyFoundationCacheDirectory() autorelease];
3584 if (!nsurlCacheDirectory)
3585 nsurlCacheDirectory = NSHomeDirectory();
3587 // As a fudge factor, use 1000 instead of 1024, in case the reported byte
3588 // count doesn't align exactly to a megabyte boundary.
3589 vm_size_t memSize = WebMemorySize() / 1024 / 1000;
3590 unsigned long long diskFreeSize = WebVolumeFreeSize(nsurlCacheDirectory) / 1024 / 1000;
3591 NSURLCache *nsurlCache = [NSURLCache sharedURLCache];
3593 unsigned cacheTotalCapacity = 0;
3594 unsigned cacheMinDeadCapacity = 0;
3595 unsigned cacheMaxDeadCapacity = 0;
3597 unsigned pageCacheCapacity = 0;
3599 NSUInteger nsurlCacheMemoryCapacity = 0;
3600 NSUInteger nsurlCacheDiskCapacity = 0;
3602 switch (cacheModel) {
3603 case WebCacheModelDocumentViewer: {
3604 // Page cache capacity (in pages)
3605 pageCacheCapacity = 0;
3607 // Object cache capacities (in bytes)
3608 if (memSize >= 4096)
3609 cacheTotalCapacity = 256 * 1024 * 1024;
3610 else if (memSize >= 3072)
3611 cacheTotalCapacity = 192 * 1024 * 1024;
3612 else if (memSize >= 2048)
3613 cacheTotalCapacity = 128 * 1024 * 1024;
3614 else if (memSize >= 1536)
3615 cacheTotalCapacity = 86 * 1024 * 1024;
3616 else if (memSize >= 1024)
3617 cacheTotalCapacity = 64 * 1024 * 1024;
3618 else if (memSize >= 512)
3619 cacheTotalCapacity = 32 * 1024 * 1024;
3620 else if (memSize >= 256)
3621 cacheTotalCapacity = 16 * 1024 * 1024;
3623 cacheMinDeadCapacity = 0;
3624 cacheMaxDeadCapacity = 0;
3626 // Foundation memory cache capacity (in bytes)
3627 nsurlCacheMemoryCapacity = 0;
3629 // Foundation disk cache capacity (in bytes)
3630 nsurlCacheDiskCapacity = [nsurlCache diskCapacity];
3634 case WebCacheModelDocumentBrowser: {
3635 // Page cache capacity (in pages)
3636 if (memSize >= 1024)
3637 pageCacheCapacity = 3;
3638 else if (memSize >= 512)
3639 pageCacheCapacity = 2;
3640 else if (memSize >= 256)
3641 pageCacheCapacity = 1;
3643 pageCacheCapacity = 0;
3645 // Object cache capacities (in bytes)
3646 if (memSize >= 4096)
3647 cacheTotalCapacity = 256 * 1024 * 1024;
3648 else if (memSize >= 3072)
3649 cacheTotalCapacity = 192 * 1024 * 1024;
3650 else if (memSize >= 2048)
3651 cacheTotalCapacity = 128 * 1024 * 1024;
3652 else if (memSize >= 1536)
3653 cacheTotalCapacity = 86 * 1024 * 1024;
3654 else if (memSize >= 1024)
3655 cacheTotalCapacity = 64 * 1024 * 1024;
3656 else if (memSize >= 512)
3657 cacheTotalCapacity = 32 * 1024 * 1024;
3658 else if (memSize >= 256)
3659 cacheTotalCapacity = 16 * 1024 * 1024;
3661 cacheMinDeadCapacity = cacheTotalCapacity / 8;
3662 cacheMaxDeadCapacity = cacheTotalCapacity / 4;
3664 // Foundation memory cache capacity (in bytes)
3665 if (memSize >= 2048)
3666 nsurlCacheMemoryCapacity = 4 * 1024 * 1024;
3667 else if (memSize >= 1024)
3668 nsurlCacheMemoryCapacity = 2 * 1024 * 1024;
3669 else if (memSize >= 512)
3670 nsurlCacheMemoryCapacity = 1 * 1024 * 1024;
3672 nsurlCacheMemoryCapacity = 512 * 1024;
3674 // Foundation disk cache capacity (in bytes)
3675 if (diskFreeSize >= 16384)
3676 nsurlCacheDiskCapacity = 50 * 1024 * 1024;
3677 else if (diskFreeSize >= 8192)
3678 nsurlCacheDiskCapacity&