2 * Copyright (C) 2005, 2006, 2007, 2008 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 "WebBackForwardListInternal.h"
34 #import "WebBaseNetscapePluginView.h"
35 #import "WebChromeClient.h"
36 #import "WebContextMenuClient.h"
37 #import "WebDOMOperationsPrivate.h"
38 #import "WebDataSourceInternal.h"
39 #import "WebDatabaseManagerInternal.h"
40 #import "WebDefaultEditingDelegate.h"
41 #import "WebDefaultPolicyDelegate.h"
42 #import "WebDefaultScriptDebugDelegate.h"
43 #import "WebDefaultUIDelegate.h"
44 #import "WebDocument.h"
45 #import "WebDocumentInternal.h"
46 #import "WebDownload.h"
47 #import "WebDownloadInternal.h"
48 #import "WebDragClient.h"
49 #import "WebDynamicScrollBarsViewInternal.h"
50 #import "WebEditingDelegate.h"
51 #import "WebEditorClient.h"
52 #import "WebFormDelegatePrivate.h"
53 #import "WebFrameInternal.h"
54 #import "WebFrameViewInternal.h"
55 #import "WebHTMLRepresentation.h"
56 #import "WebHTMLViewInternal.h"
57 #import "WebHistoryItemInternal.h"
58 #import "WebIconDatabaseInternal.h"
59 #import "WebInspector.h"
60 #import "WebInspectorClient.h"
61 #import "WebKitErrors.h"
62 #import "WebKitLogging.h"
63 #import "WebKitNSStringExtras.h"
64 #import "WebKitStatisticsPrivate.h"
65 #import "WebKitSystemBits.h"
66 #import "WebKitVersionChecks.h"
67 #import "WebLocalizableStrings.h"
68 #import "WebNSDataExtras.h"
69 #import "WebNSDataExtrasPrivate.h"
70 #import "WebNSDictionaryExtras.h"
71 #import "WebNSEventExtras.h"
72 #import "WebNSObjectExtras.h"
73 #import "WebNSPasteboardExtras.h"
74 #import "WebNSPrintOperationExtras.h"
75 #import "WebNSURLExtras.h"
76 #import "WebNSURLRequestExtras.h"
77 #import "WebNSUserDefaultsExtras.h"
78 #import "WebNSViewExtras.h"
79 #import "WebPDFView.h"
80 #import "WebPanelAuthenticationHandler.h"
81 #import "WebPasteboardHelper.h"
82 #import "WebPluginDatabase.h"
83 #import "WebPolicyDelegate.h"
84 #import "WebPreferenceKeysPrivate.h"
85 #import "WebPreferencesPrivate.h"
86 #import "WebScriptDebugServerPrivate.h"
87 #import "WebUIDelegate.h"
88 #import "WebUIDelegatePrivate.h"
89 #import <CoreFoundation/CFSet.h>
90 #import <Foundation/NSURLConnection.h>
91 #import <JavaScriptCore/Assertions.h>
92 #import <JavaScriptCore/HashTraits.h>
93 #import <JavaScriptCore/RefPtr.h>
94 #import <JavaScriptCore/array_object.h>
95 #import <JavaScriptCore/date_object.h>
96 #import <WebCore/ApplicationCacheStorage.h>
97 #import <WebCore/Cache.h>
98 #import <WebCore/ColorMac.h>
99 #import <WebCore/Document.h>
100 #import <WebCore/DocumentLoader.h>
101 #import <WebCore/DragController.h>
102 #import <WebCore/DragData.h>
103 #import <WebCore/Editor.h>
104 #import <WebCore/ExceptionHandlers.h>
105 #import <WebCore/Frame.h>
106 #import <WebCore/FrameLoader.h>
107 #import <WebCore/FrameTree.h>
108 #import <WebCore/HTMLNames.h>
109 #import <WebCore/HistoryItem.h>
110 #import <WebCore/Logging.h>
111 #import <WebCore/MIMETypeRegistry.h>
112 #import <WebCore/Page.h>
113 #import <WebCore/PageCache.h>
114 #import <WebCore/PageGroup.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/WebCoreObjCExtras.h>
121 #import <WebCore/WebCoreTextRenderer.h>
122 #import <WebCore/WebCoreView.h>
123 #import <WebCore/kjs_proxy.h>
124 #import <WebKit/DOM.h>
125 #import <WebKit/DOMExtensions.h>
126 #import <WebKit/DOMPrivate.h>
127 #import <WebKitSystemInterface.h>
128 #import <kjs/InitializeThreading.h>
129 #import <mach-o/dyld.h>
130 #import <objc/objc-auto.h>
131 #import <objc/objc-runtime.h>
132 #import <sys/param.h>
134 #if ENABLE(DASHBOARD_SUPPORT)
135 #import <WebKit/WebDashboardRegion.h>
138 using namespace WebCore;
141 #if defined(__ppc__) || defined(__ppc64__)
142 #define PROCESSOR "PPC"
143 #elif defined(__i386__) || defined(__x86_64__)
144 #define PROCESSOR "Intel"
146 #error Unknown architecture
149 #define FOR_EACH_RESPONDER_SELECTOR(macro) \
151 macro(alignJustified) \
154 macro(capitalizeWord) \
155 macro(centerSelectionInVisibleArea) \
156 macro(changeAttributes) \
157 macro(changeBaseWritingDirection) \
158 macro(changeBaseWritingDirectionToLTR) \
159 macro(changeBaseWritingDirectionToRTL) \
161 macro(changeDocumentBackgroundColor) \
163 macro(changeSpelling) \
164 macro(checkSpelling) \
170 macro(deleteBackward) \
171 macro(deleteBackwardByDecomposingPreviousCharacter) \
172 macro(deleteForward) \
173 macro(deleteToBeginningOfLine) \
174 macro(deleteToBeginningOfParagraph) \
175 macro(deleteToEndOfLine) \
176 macro(deleteToEndOfParagraph) \
177 macro(deleteToMark) \
178 macro(deleteWordBackward) \
179 macro(deleteWordForward) \
180 macro(ignoreSpelling) \
182 macro(insertBacktab) \
183 macro(insertLineBreak) \
184 macro(insertNewline) \
185 macro(insertNewlineIgnoringFieldEditor) \
186 macro(insertParagraphSeparator) \
188 macro(insertTabIgnoringFieldEditor) \
189 macro(lowercaseWord) \
190 macro(moveBackward) \
191 macro(moveBackwardAndModifySelection) \
193 macro(moveDownAndModifySelection) \
195 macro(moveForwardAndModifySelection) \
197 macro(moveLeftAndModifySelection) \
198 macro(moveParagraphBackwardAndModifySelection) \
199 macro(moveParagraphForwardAndModifySelection) \
201 macro(moveRightAndModifySelection) \
202 macro(moveToBeginningOfDocument) \
203 macro(moveToBeginningOfDocumentAndModifySelection) \
204 macro(moveToBeginningOfLine) \
205 macro(moveToBeginningOfLineAndModifySelection) \
206 macro(moveToBeginningOfParagraph) \
207 macro(moveToBeginningOfParagraphAndModifySelection) \
208 macro(moveToBeginningOfSentence) \
209 macro(moveToBeginningOfSentenceAndModifySelection) \
210 macro(moveToEndOfDocument) \
211 macro(moveToEndOfDocumentAndModifySelection) \
212 macro(moveToEndOfLine) \
213 macro(moveToEndOfLineAndModifySelection) \
214 macro(moveToEndOfParagraph) \
215 macro(moveToEndOfParagraphAndModifySelection) \
216 macro(moveToEndOfSentence) \
217 macro(moveToEndOfSentenceAndModifySelection) \
219 macro(moveUpAndModifySelection) \
220 macro(moveWordBackward) \
221 macro(moveWordBackwardAndModifySelection) \
222 macro(moveWordForward) \
223 macro(moveWordForwardAndModifySelection) \
224 macro(moveWordLeft) \
225 macro(moveWordLeftAndModifySelection) \
226 macro(moveWordRight) \
227 macro(moveWordRightAndModifySelection) \
230 macro(pageDownAndModifySelection) \
232 macro(pageUpAndModifySelection) \
234 macro(pasteAsPlainText) \
235 macro(pasteAsRichText) \
237 macro(performFindPanelAction) \
238 macro(scrollLineDown) \
239 macro(scrollLineUp) \
240 macro(scrollPageDown) \
241 macro(scrollPageUp) \
242 macro(scrollToBeginningOfDocument) \
243 macro(scrollToEndOfDocument) \
246 macro(selectParagraph) \
247 macro(selectSentence) \
248 macro(selectToMark) \
251 macro(showGuessPanel) \
252 macro(startSpeaking) \
253 macro(stopSpeaking) \
256 macro(swapWithMark) \
257 macro(takeFindStringFromSelection) \
258 macro(toggleBaseWritingDirection) \
262 macro(uppercaseWord) \
264 macro(yankAndSelect) \
266 #define WebKitOriginalTopPrintingMarginKey @"WebKitOriginalTopMargin"
267 #define WebKitOriginalBottomPrintingMarginKey @"WebKitOriginalBottomMargin"
269 #define KeyboardUIModeDidChangeNotification @"com.apple.KeyboardUIModeDidChange"
270 #define AppleKeyboardUIMode CFSTR("AppleKeyboardUIMode")
271 #define UniversalAccessDomain CFSTR("com.apple.universalaccess")
273 static BOOL s_didSetCacheModel;
274 static WebCacheModel s_cacheModel = WebCacheModelDocumentViewer;
276 static BOOL applicationIsTerminating;
277 static int pluginDatabaseClientCount = 0;
279 @interface NSSpellChecker (AppKitSecretsIKnow)
280 - (void)_preflightChosenSpellServer;
283 @interface NSView (AppKitSecretsIKnow)
284 - (NSView *)_hitTest:(NSPoint *)aPoint dragTypes:(NSSet *)types;
285 - (void)_autoscrollForDraggingInfo:(id)dragInfo timeDelta:(NSTimeInterval)repeatDelta;
286 - (BOOL)_shouldAutoscrollForDraggingInfo:(id)dragInfo;
289 @interface NSWindow (AppKitSecretsIKnow)
290 - (id)_oldFirstResponderBeforeBecoming;
293 @interface NSObject (ValidateWithoutDelegate)
294 - (BOOL)validateUserInterfaceItemWithoutDelegate:(id <NSValidatedUserInterfaceItem>)item;
297 @interface _WebSafeForwarder : NSObject
299 id target; // Non-retained. Don't retain delegates.
301 BOOL catchExceptions;
303 - (id)initWithTarget:(id)target defaultTarget:(id)defaultTarget catchExceptions:(BOOL)catchExceptions;
306 @interface WebViewPrivate : NSObject {
311 id UIDelegateForwarder;
312 id resourceProgressDelegate;
315 id policyDelegateForwarder;
316 id frameLoadDelegate;
317 id frameLoadDelegateForwarder;
318 id <WebFormDelegate> formDelegate;
320 id editingDelegateForwarder;
321 id scriptDebugDelegate;
322 id scriptDebugDelegateForwarder;
324 WebInspector *inspector;
328 float zoomMultiplier;
329 BOOL zoomMultiplierIsTextOnly;
331 NSString *applicationNameForUserAgent;
333 BOOL userAgentOverridden;
335 WebPreferences *preferences;
336 BOOL useSiteSpecificSpoofing;
338 NSWindow *hostWindow;
340 int programmaticFocusCount;
342 WebResourceDelegateImplementationCache resourceLoadDelegateImplementations;
343 WebFrameLoadDelegateImplementationCache frameLoadDelegateImplementations;
345 void *observationInfo;
348 BOOL shouldCloseWithWindow;
349 BOOL mainFrameDocumentReady;
350 BOOL drawsBackground;
352 BOOL tabKeyCyclesThroughElementsChanged;
353 BOOL becomingFirstResponder;
354 BOOL becomingFirstResponderFromOutside;
355 BOOL hoverFeedbackSuspended;
357 BOOL catchesDelegateExceptions;
359 NSColor *backgroundColor;
361 NSString *mediaStyle;
363 BOOL hasSpellCheckerDocumentTag;
364 NSInteger spellCheckerDocumentTag;
366 BOOL smartInsertDeleteEnabled;
368 #if ENABLE(DASHBOARD_SUPPORT)
369 BOOL dashboardBehaviorAlwaysSendMouseEventsToAllWindows;
370 BOOL dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns;
371 BOOL dashboardBehaviorAlwaysAcceptsFirstMouse;
372 BOOL dashboardBehaviorAllowWheelScrolling;
375 // WebKit has both a global plug-in database and a separate, per WebView plug-in database. Dashboard uses the per WebView database.
376 WebPluginDatabase *pluginDatabase;
378 HashMap<unsigned long, RetainPtr<id> >* identifierMap;
380 BOOL _keyboardUIModeAccessed;
381 KeyboardUIMode _keyboardUIMode;
385 @interface WebView (WebFileInternal)
386 - (WebFrame *)_selectedOrMainFrame;
388 - (WebFrameView *)_frameViewAtWindowPoint:(NSPoint)point;
389 - (WebFrame *)_focusedFrame;
390 + (void)_preflightSpellChecker;
391 - (BOOL)_continuousCheckingAllowed;
392 - (NSResponder *)_responderForResponderOperations;
395 @interface WebView (WebCallDelegateFunctions)
398 NSString *WebElementDOMNodeKey = @"WebElementDOMNode";
399 NSString *WebElementFrameKey = @"WebElementFrame";
400 NSString *WebElementImageKey = @"WebElementImage";
401 NSString *WebElementImageAltStringKey = @"WebElementImageAltString";
402 NSString *WebElementImageRectKey = @"WebElementImageRect";
403 NSString *WebElementImageURLKey = @"WebElementImageURL";
404 NSString *WebElementIsSelectedKey = @"WebElementIsSelected";
405 NSString *WebElementLinkLabelKey = @"WebElementLinkLabel";
406 NSString *WebElementLinkTargetFrameKey = @"WebElementTargetFrame";
407 NSString *WebElementLinkTitleKey = @"WebElementLinkTitle";
408 NSString *WebElementLinkURLKey = @"WebElementLinkURL";
409 NSString *WebElementSpellingToolTipKey = @"WebElementSpellingToolTip";
410 NSString *WebElementTitleKey = @"WebElementTitle";
411 NSString *WebElementLinkIsLiveKey = @"WebElementLinkIsLive";
412 NSString *WebElementIsContentEditableKey = @"WebElementIsContentEditableKey";
414 NSString *WebViewProgressStartedNotification = @"WebProgressStartedNotification";
415 NSString *WebViewProgressEstimateChangedNotification = @"WebProgressEstimateChangedNotification";
416 NSString *WebViewProgressFinishedNotification = @"WebProgressFinishedNotification";
418 NSString * const WebViewDidBeginEditingNotification = @"WebViewDidBeginEditingNotification";
419 NSString * const WebViewDidChangeNotification = @"WebViewDidChangeNotification";
420 NSString * const WebViewDidEndEditingNotification = @"WebViewDidEndEditingNotification";
421 NSString * const WebViewDidChangeTypingStyleNotification = @"WebViewDidChangeTypingStyleNotification";
422 NSString * const WebViewDidChangeSelectionNotification = @"WebViewDidChangeSelectionNotification";
424 enum { WebViewVersion = 4 };
426 #define timedLayoutSize 4096
428 static NSMutableSet *schemesWithRepresentationsSet;
430 NSString *_WebCanGoBackKey = @"canGoBack";
431 NSString *_WebCanGoForwardKey = @"canGoForward";
432 NSString *_WebEstimatedProgressKey = @"estimatedProgress";
433 NSString *_WebIsLoadingKey = @"isLoading";
434 NSString *_WebMainFrameIconKey = @"mainFrameIcon";
435 NSString *_WebMainFrameTitleKey = @"mainFrameTitle";
436 NSString *_WebMainFrameURLKey = @"mainFrameURL";
437 NSString *_WebMainFrameDocumentKey = @"mainFrameDocument";
439 @interface WebProgressItem : NSObject
442 long long bytesReceived;
443 long long estimatedLength;
447 @implementation WebProgressItem
450 static BOOL continuousSpellCheckingEnabled;
451 #ifndef BUILDING_ON_TIGER
452 static BOOL grammarCheckingEnabled;
455 @implementation WebViewPrivate
457 #ifndef BUILDING_ON_TIGER
460 WebCoreObjCFinalizeOnMainThread(self);
469 KJS::initializeThreading();
472 zoomMultiplierIsTextOnly = YES;
473 #if ENABLE(DASHBOARD_SUPPORT)
474 dashboardBehaviorAllowWheelScrolling = YES;
476 shouldCloseWithWindow = objc_collecting_enabled();
477 continuousSpellCheckingEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebContinuousSpellCheckingEnabled];
479 #ifndef BUILDING_ON_TIGER
480 grammarCheckingEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebGrammarCheckingEnabled];
482 userAgent = new String;
486 identifierMap = new HashMap<unsigned long, RetainPtr<id> >();
487 pluginDatabaseClientCount++;
495 ASSERT(!preferences);
498 delete identifierMap;
500 [applicationNameForUserAgent release];
501 [backgroundColor release];
504 [hostWindow release];
506 [policyDelegateForwarder release];
507 [UIDelegateForwarder release];
508 [frameLoadDelegateForwarder release];
509 [editingDelegateForwarder release];
510 [scriptDebugDelegateForwarder release];
512 [mediaStyle release];
519 ASSERT_MAIN_THREAD();
522 delete identifierMap;
529 @implementation WebView (AllWebViews)
531 static CFSetCallBacks NonRetainingSetCallbacks = {
540 static CFMutableSetRef allWebViewsSet;
542 + (void)_makeAllWebViewsPerformSelector:(SEL)selector
547 [(NSMutableSet *)allWebViewsSet makeObjectsPerformSelector:selector];
550 - (void)_removeFromAllWebViewsSet
553 CFSetRemoveValue(allWebViewsSet, self);
556 - (void)_addToAllWebViewsSet
559 allWebViewsSet = CFSetCreateMutable(NULL, 0, &NonRetainingSetCallbacks);
561 CFSetSetValue(allWebViewsSet, self);
566 @implementation WebView (WebPrivate)
568 #ifdef DEBUG_WIDGET_DRAWING
569 static bool debugWidget = true;
570 - (void)drawRect:(NSRect)rect
572 [[NSColor blueColor] set];
575 NSRect htmlViewRect = [[[[self mainFrame] frameView] documentView] frame];
578 while (debugWidget) {
583 NSLog (@"%s: rect: (%0.f,%0.f) %0.f %0.f, htmlViewRect: (%0.f,%0.f) %0.f %0.f\n",
584 __PRETTY_FUNCTION__, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height,
585 htmlViewRect.origin.x, htmlViewRect.origin.y, htmlViewRect.size.width, htmlViewRect.size.height
588 [super drawRect:rect];
592 + (BOOL)_scriptDebuggerEnabled
595 return [[NSUserDefaults standardUserDefaults] boolForKey:@"WebKitScriptDebuggerEnabled"];
597 return YES; // always enable in debug builds
601 + (NSArray *)_supportedMIMETypes
603 // Load the plug-in DB allowing plug-ins to install types.
604 [WebPluginDatabase sharedDatabase];
605 return [[WebFrameView _viewTypesAllowImageTypeOmission:NO] allKeys];
608 + (NSArray *)_supportedFileExtensions
610 NSMutableSet *extensions = [[NSMutableSet alloc] init];
611 NSArray *MIMETypes = [self _supportedMIMETypes];
612 NSEnumerator *enumerator = [MIMETypes objectEnumerator];
614 while ((MIMEType = [enumerator nextObject]) != nil) {
615 NSArray *extensionsForType = WKGetExtensionsForMIMEType(MIMEType);
616 if (extensionsForType) {
617 [extensions addObjectsFromArray:extensionsForType];
620 NSArray *uniqueExtensions = [extensions allObjects];
621 [extensions release];
622 return uniqueExtensions;
625 + (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType;
627 MIMEType = [MIMEType lowercaseString];
628 Class viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:YES] _webkit_objectForMIMEType:MIMEType];
629 Class repClass = [[WebDataSource _repTypesAllowImageTypeOmission:YES] _webkit_objectForMIMEType:MIMEType];
631 if (!viewClass || !repClass || [[WebPDFView supportedMIMETypes] containsObject:MIMEType]) {
632 // Our optimization to avoid loading the plug-in DB and image types for the HTML case failed.
633 // Load the plug-in DB allowing plug-ins to install types.
634 [WebPluginDatabase sharedDatabase];
636 // Load the image types and get the view class and rep class. This should be the fullest picture of all handled types.
637 viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:NO] _webkit_objectForMIMEType:MIMEType];
638 repClass = [[WebDataSource _repTypesAllowImageTypeOmission:NO] _webkit_objectForMIMEType:MIMEType];
641 if (viewClass && repClass) {
642 // Special-case WebHTMLView for text types that shouldn't be shown.
643 if (viewClass == [WebHTMLView class] &&
644 repClass == [WebHTMLRepresentation class] &&
645 [[WebHTMLView unsupportedTextMIMETypes] containsObject:MIMEType]) {
658 - (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType;
660 if ([[self class] _viewClass:vClass andRepresentationClass:rClass forMIMEType:MIMEType])
663 if (_private->pluginDatabase) {
664 WebBasePluginPackage *pluginPackage = [_private->pluginDatabase pluginForMIMEType:MIMEType];
667 *vClass = [WebHTMLView class];
669 *rClass = [WebHTMLRepresentation class];
677 + (void)_setAlwaysUseATSU:(BOOL)f
679 WebCoreSetAlwaysUseATSU(f);
682 + (BOOL)canShowFile:(NSString *)path
684 return [[self class] canShowMIMEType:[WebView _MIMETypeForFile:path]];
687 + (NSString *)suggestedFileExtensionForMIMEType:(NSString *)type
689 return WKGetPreferredExtensionForMIMEType(type);
694 if (!_private || _private->closed)
701 if (!_private || _private->closed)
704 if (Frame* mainFrame = core([self mainFrame]))
705 mainFrame->loader()->detachFromParent();
707 [self _removeFromAllWebViewsSet];
708 [self setHostWindow:nil];
710 [self setDownloadDelegate:nil];
711 [self setEditingDelegate:nil];
712 [self setFrameLoadDelegate:nil];
713 [self setPolicyDelegate:nil];
714 [self setResourceLoadDelegate:nil];
715 [self setScriptDebugDelegate:nil];
716 [self setUIDelegate:nil];
718 [_private->inspector webViewClosed];
720 // setHostWindow:nil must be called before this value is set (see 5408186)
721 _private->closed = YES;
723 // To avoid leaks, call removeDragCaret in case it wasn't called after moveDragCaretToPoint.
724 [self removeDragCaret];
726 // Deleteing the WebCore::Page will clear the page cache so we call destroy on
727 // all the plug-ins in the page cache to break any retain cycles.
728 // See comment in HistoryItem::releaseAllPendingPageCaches() for more information.
729 delete _private->page;
732 if (_private->hasSpellCheckerDocumentTag) {
733 [[NSSpellChecker sharedSpellChecker] closeSpellDocumentWithTag:_private->spellCheckerDocumentTag];
734 _private->hasSpellCheckerDocumentTag = NO;
737 [[NSDistributedNotificationCenter defaultCenter] removeObserver:self];
738 [[NSNotificationCenter defaultCenter] removeObserver:self];
740 [WebPreferences _removeReferenceForIdentifier:[self preferencesIdentifier]];
742 WebPreferences *preferences = _private->preferences;
743 _private->preferences = nil;
744 [preferences didRemoveFromWebView];
745 [preferences release];
747 pluginDatabaseClientCount--;
749 // Make sure to close both sets of plug-ins databases because plug-ins need an opportunity to clean up files, etc.
751 // Unload the WebView local plug-in database.
752 if (_private->pluginDatabase) {
753 [_private->pluginDatabase close];
754 [_private->pluginDatabase release];
755 _private->pluginDatabase = nil;
758 // Keep the global plug-in database active until the app terminates to avoid having to reload plug-in bundles.
759 if (!pluginDatabaseClientCount && applicationIsTerminating)
760 [WebPluginDatabase closeSharedDatabase];
763 + (NSString *)_MIMETypeForFile:(NSString *)path
765 NSString *extension = [path pathExtension];
766 NSString *MIMEType = nil;
768 // Get the MIME type from the extension.
769 if ([extension length] != 0) {
770 MIMEType = WKGetMIMETypeForExtension(extension);
773 // If we can't get a known MIME type from the extension, sniff.
774 if ([MIMEType length] == 0 || [MIMEType isEqualToString:@"application/octet-stream"]) {
775 NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:path];
776 NSData *data = [handle readDataOfLength:WEB_GUESS_MIME_TYPE_PEEK_LENGTH];
778 if ([data length] != 0) {
779 MIMEType = [data _webkit_guessedMIMEType];
781 if ([MIMEType length] == 0) {
782 MIMEType = @"application/octet-stream";
789 - (WebDownload *)_downloadURL:(NSURL *)URL
793 NSURLRequest *request = [[NSURLRequest alloc] initWithURL:URL];
794 WebDownload *download = [WebDownload _downloadWithRequest:request
795 delegate:_private->downloadDelegate
802 - (WebView *)_openNewWindowWithRequest:(NSURLRequest *)request
804 NSDictionary *features = [[NSDictionary alloc] init];
805 WebView *newWindowWebView = [[self _UIDelegateForwarder] webView:self
806 createWebViewWithRequest:nil
807 windowFeatures:features];
809 if (!newWindowWebView)
812 CallUIDelegate(newWindowWebView, @selector(webViewShow:));
813 return newWindowWebView;
816 - (WebInspector *)inspector
818 if (!_private->inspector)
819 _private->inspector = [[WebInspector alloc] initWithWebView:self];
820 return _private->inspector;
823 - (WebCore::Page*)page
825 return _private->page;
828 - (NSMenu *)_menuForElement:(NSDictionary *)element defaultItems:(NSArray *)items
830 NSArray *defaultMenuItems = [[WebDefaultUIDelegate sharedUIDelegate] webView:self contextMenuItemsForElement:element defaultMenuItems:items];
832 NSArray *menuItems = CallUIDelegate(self, @selector(webView:contextMenuItemsForElement:defaultMenuItems:), element, defaultMenuItems);
836 unsigned count = [menuItems count];
840 NSMenu *menu = [[NSMenu alloc] init];
841 for (unsigned i = 0; i < count; i++)
842 [menu addItem:[menuItems objectAtIndex:i]];
844 return [menu autorelease];
847 - (void)_mouseDidMoveOverElement:(NSDictionary *)dictionary modifierFlags:(NSUInteger)modifierFlags
849 // We originally intended to call this delegate method sometimes with a nil dictionary, but due to
850 // a bug dating back to WebKit 1.0 this delegate was never called with nil! Unfortunately we can't
851 // start calling this with nil since it will break Adobe Help Viewer, and possibly other clients.
854 CallUIDelegate(self, @selector(webView:mouseDidMoveOverElement:modifierFlags:), dictionary, modifierFlags);
857 - (void)_loadBackForwardListFromOtherView:(WebView *)otherView
862 if (!otherView->_private->page)
865 // It turns out the right combination of behavior is done with the back/forward load
866 // type. (See behavior matrix at the top of WebFramePrivate.) So we copy all the items
867 // in the back forward list, and go to the current one.
869 BackForwardList* backForwardList = _private->page->backForwardList();
870 ASSERT(!backForwardList->currentItem()); // destination list should be empty
872 BackForwardList* otherBackForwardList = otherView->_private->page->backForwardList();
873 if (!otherBackForwardList->currentItem())
874 return; // empty back forward list, bail
876 HistoryItem* newItemToGoTo = 0;
878 int lastItemIndex = otherBackForwardList->forwardListCount();
879 for (int i = -otherBackForwardList->backListCount(); i <= lastItemIndex; ++i) {
881 // If this item is showing , save away its current scroll and form state,
882 // since that might have changed since loading and it is normally not saved
883 // until we leave that page.
884 otherView->_private->page->mainFrame()->loader()->saveDocumentAndScrollState();
886 RefPtr<HistoryItem> newItem = otherBackForwardList->itemAtIndex(i)->copy();
888 newItemToGoTo = newItem.get();
889 backForwardList->addItem(newItem.release());
892 ASSERT(newItemToGoTo);
893 _private->page->goToItem(newItemToGoTo, FrameLoadTypeIndexedBackForward);
896 - (void)_setFormDelegate: (id<WebFormDelegate>)delegate
898 _private->formDelegate = delegate;
901 - (id<WebFormDelegate>)_formDelegate
903 return _private->formDelegate;
906 - (BOOL)_needsAdobeFrameReloadingQuirk
908 static BOOL checked = NO;
909 static BOOL needsQuirk = NO;
914 needsQuirk = WKAppVersionCheckLessThan(@"com.adobe.Acrobat", -1, 9.0)
915 || WKAppVersionCheckLessThan(@"com.adobe.Acrobat.Pro", -1, 9.0)
916 || WKAppVersionCheckLessThan(@"com.adobe.Reader", -1, 9.0)
917 || WKAppVersionCheckLessThan(@"com.adobe.distiller", -1, 9.0)
918 || WKAppVersionCheckLessThan(@"com.adobe.Contribute", -1, 4.2)
919 || WKAppVersionCheckLessThan(@"com.adobe.dreamweaver-9.0", -1, 9.1)
920 || WKAppVersionCheckLessThan(@"com.macromedia.fireworks", -1, 9.1)
921 || WKAppVersionCheckLessThan(@"com.adobe.InCopy", -1, 5.1)
922 || WKAppVersionCheckLessThan(@"com.adobe.InDesign", -1, 5.1)
923 || WKAppVersionCheckLessThan(@"com.adobe.Soundbooth", -1, 2);
929 - (BOOL)_needsKeyboardEventDisambiguationQuirks
931 static BOOL checked = NO;
932 static BOOL needsQuirks = NO;
937 needsQuirks = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_IE_COMPATIBLE_KEYBOARD_EVENT_DISPATCH)
938 && ![[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.Safari"];
944 - (void)_preferencesChangedNotification:(NSNotification *)notification
946 WebPreferences *preferences = (WebPreferences *)[notification object];
947 ASSERT(preferences == [self preferences]);
949 if (!_private->userAgentOverridden)
950 *_private->userAgent = String();
952 // Cache this value so we don't have to read NSUserDefaults on each page load
953 _private->useSiteSpecificSpoofing = [preferences _useSiteSpecificSpoofing];
955 // Update corresponding WebCore Settings object.
959 Settings* settings = _private->page->settings();
961 settings->setCursiveFontFamily([preferences cursiveFontFamily]);
962 settings->setDefaultFixedFontSize([preferences defaultFixedFontSize]);
963 settings->setDefaultFontSize([preferences defaultFontSize]);
964 settings->setDefaultTextEncodingName([preferences defaultTextEncodingName]);
965 settings->setFantasyFontFamily([preferences fantasyFontFamily]);
966 settings->setFixedFontFamily([preferences fixedFontFamily]);
967 settings->setForceFTPDirectoryListings([preferences _forceFTPDirectoryListings]);
968 settings->setFTPDirectoryTemplatePath([preferences _ftpDirectoryTemplatePath]);
969 settings->setLocalStorageDatabasePath([preferences _localStorageDatabasePath]);
970 settings->setJavaEnabled([preferences isJavaEnabled]);
971 settings->setJavaScriptEnabled([preferences isJavaScriptEnabled]);
972 settings->setJavaScriptCanOpenWindowsAutomatically([preferences javaScriptCanOpenWindowsAutomatically]);
973 settings->setMinimumFontSize([preferences minimumFontSize]);
974 settings->setMinimumLogicalFontSize([preferences minimumLogicalFontSize]);
975 settings->setPluginsEnabled([preferences arePlugInsEnabled]);
976 settings->setPrivateBrowsingEnabled([preferences privateBrowsingEnabled]);
977 settings->setSansSerifFontFamily([preferences sansSerifFontFamily]);
978 settings->setSerifFontFamily([preferences serifFontFamily]);
979 settings->setStandardFontFamily([preferences standardFontFamily]);
980 settings->setLoadsImagesAutomatically([preferences loadsImagesAutomatically]);
981 settings->setShouldPrintBackgrounds([preferences shouldPrintBackgrounds]);
982 settings->setTextAreasAreResizable([preferences textAreasAreResizable]);
983 settings->setShrinksStandaloneImagesToFit([preferences shrinksStandaloneImagesToFit]);
984 settings->setEditableLinkBehavior(core([preferences editableLinkBehavior]));
985 settings->setDOMPasteAllowed([preferences isDOMPasteAllowed]);
986 settings->setUsesPageCache([self usesPageCache]);
987 settings->setShowsURLsInToolTips([preferences showsURLsInToolTips]);
988 settings->setDeveloperExtrasEnabled([preferences developerExtrasEnabled]);
989 settings->setAuthorAndUserStylesEnabled([preferences authorAndUserStylesEnabled]);
990 if ([preferences userStyleSheetEnabled]) {
991 NSString* location = [[preferences userStyleSheetLocation] _web_originalDataAsString];
992 settings->setUserStyleSheetLocation([NSURL URLWithString:(location ? location : @"")]);
994 settings->setUserStyleSheetLocation([NSURL URLWithString:@""]);
995 settings->setNeedsAdobeFrameReloadingQuirk([self _needsAdobeFrameReloadingQuirk]);
996 settings->setNeedsKeyboardEventDisambiguationQuirks([self _needsKeyboardEventDisambiguationQuirks]);
997 settings->setNeedsSiteSpecificQuirks(_private->useSiteSpecificSpoofing);
998 settings->setWebArchiveDebugModeEnabled([preferences webArchiveDebugModeEnabled]);
999 settings->disableRangeMutationForOldAppleMail(WKAppVersionCheckLessThan(@"com.apple.mail", -1, 4.0));
1000 settings->setOfflineWebApplicationCacheEnabled([preferences offlineWebApplicationCacheEnabled]);
1003 static inline IMP getMethod(id o, SEL s)
1005 return [o respondsToSelector:s] ? [o methodForSelector:s] : 0;
1008 - (void)_cacheResourceLoadDelegateImplementations
1010 WebResourceDelegateImplementationCache *cache = &_private->resourceLoadDelegateImplementations;
1011 id delegate = _private->resourceProgressDelegate;
1014 bzero(cache, sizeof(WebResourceDelegateImplementationCache));
1018 cache->didCancelAuthenticationChallengeFunc = getMethod(delegate, @selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:));
1019 cache->didFailLoadingWithErrorFromDataSourceFunc = getMethod(delegate, @selector(webView:resource:didFailLoadingWithError:fromDataSource:));
1020 cache->didFinishLoadingFromDataSourceFunc = getMethod(delegate, @selector(webView:resource:didFinishLoadingFromDataSource:));
1021 cache->didLoadResourceFromMemoryCacheFunc = getMethod(delegate, @selector(webView:didLoadResourceFromMemoryCache:response:length:fromDataSource:));
1022 cache->didReceiveAuthenticationChallengeFunc = getMethod(delegate, @selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:));
1023 cache->didReceiveContentLengthFunc = getMethod(delegate, @selector(webView:resource:didReceiveContentLength:fromDataSource:));
1024 cache->didReceiveResponseFunc = getMethod(delegate, @selector(webView:resource:didReceiveResponse:fromDataSource:));
1025 cache->identifierForRequestFunc = getMethod(delegate, @selector(webView:identifierForInitialRequest:fromDataSource:));
1026 cache->plugInFailedWithErrorFunc = getMethod(delegate, @selector(webView:plugInFailedWithError:dataSource:));
1027 cache->willCacheResponseFunc = getMethod(delegate, @selector(webView:resource:willCacheResponse:fromDataSource:));
1028 cache->willSendRequestFunc = getMethod(delegate, @selector(webView:resource:willSendRequest:redirectResponse:fromDataSource:));
1031 WebResourceDelegateImplementationCache* WebViewGetResourceLoadDelegateImplementations(WebView *webView)
1033 static WebResourceDelegateImplementationCache empty;
1036 return &webView->_private->resourceLoadDelegateImplementations;
1039 - (void)_cacheFrameLoadDelegateImplementations
1041 WebFrameLoadDelegateImplementationCache *cache = &_private->frameLoadDelegateImplementations;
1042 id delegate = _private->frameLoadDelegate;
1045 bzero(cache, sizeof(WebFrameLoadDelegateImplementationCache));
1049 cache->didCancelClientRedirectForFrameFunc = getMethod(delegate, @selector(webView:didCancelClientRedirectForFrame:));
1050 cache->didChangeLocationWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didChangeLocationWithinPageForFrame:));
1051 cache->didClearWindowObjectForFrameFunc = getMethod(delegate, @selector(webView:didClearWindowObject:forFrame:));
1052 cache->didCommitLoadForFrameFunc = getMethod(delegate, @selector(webView:didCommitLoadForFrame:));
1053 cache->didFailLoadWithErrorForFrameFunc = getMethod(delegate, @selector(webView:didFailLoadWithError:forFrame:));
1054 cache->didFailProvisionalLoadWithErrorForFrameFunc = getMethod(delegate, @selector(webView:didFailProvisionalLoadWithError:forFrame:));
1055 cache->didFinishDocumentLoadForFrameFunc = getMethod(delegate, @selector(webView:didFinishDocumentLoadForFrame:));
1056 cache->didFinishLoadForFrameFunc = getMethod(delegate, @selector(webView:didFinishLoadForFrame:));
1057 cache->didFirstLayoutInFrameFunc = getMethod(delegate, @selector(webView:didFirstLayoutInFrame:));
1058 cache->didHandleOnloadEventsForFrameFunc = getMethod(delegate, @selector(webView:didHandleOnloadEventsForFrame:));
1059 cache->didReceiveIconForFrameFunc = getMethod(delegate, @selector(webView:didReceiveIcon:forFrame:));
1060 cache->didReceiveServerRedirectForProvisionalLoadForFrameFunc = getMethod(delegate, @selector(webView:didReceiveServerRedirectForProvisionalLoadForFrame:));
1061 cache->didReceiveTitleForFrameFunc = getMethod(delegate, @selector(webView:didReceiveTitle:forFrame:));
1062 cache->didStartProvisionalLoadForFrameFunc = getMethod(delegate, @selector(webView:didStartProvisionalLoadForFrame:));
1063 cache->willCloseFrameFunc = getMethod(delegate, @selector(webView:willCloseFrame:));
1064 cache->willPerformClientRedirectToURLDelayFireDateForFrameFunc = getMethod(delegate, @selector(webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:));
1065 cache->windowScriptObjectAvailableFunc = getMethod(delegate, @selector(webView:windowScriptObjectAvailable:));
1068 WebFrameLoadDelegateImplementationCache* WebViewGetFrameLoadDelegateImplementations(WebView *webView)
1070 static WebFrameLoadDelegateImplementationCache empty;
1073 return &webView->_private->frameLoadDelegateImplementations;
1076 - (id)_policyDelegateForwarder
1078 if (!_private->policyDelegateForwarder)
1079 _private->policyDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->policyDelegate defaultTarget:[WebDefaultPolicyDelegate sharedPolicyDelegate] catchExceptions:_private->catchesDelegateExceptions];
1080 return _private->policyDelegateForwarder;
1083 - (id)_UIDelegateForwarder
1085 if (!_private->UIDelegateForwarder)
1086 _private->UIDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->UIDelegate defaultTarget:[WebDefaultUIDelegate sharedUIDelegate] catchExceptions:_private->catchesDelegateExceptions];
1087 return _private->UIDelegateForwarder;
1090 - (id)_editingDelegateForwarder
1092 // This can be called during window deallocation by QTMovieView in the QuickTime Cocoa Plug-in.
1093 // Not sure if that is a bug or not.
1097 if (!_private->editingDelegateForwarder)
1098 _private->editingDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->editingDelegate defaultTarget:[WebDefaultEditingDelegate sharedEditingDelegate] catchExceptions:_private->catchesDelegateExceptions];
1099 return _private->editingDelegateForwarder;
1102 - (id)_scriptDebugDelegateForwarder
1104 if (!_private->scriptDebugDelegateForwarder)
1105 _private->scriptDebugDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->scriptDebugDelegate defaultTarget:[WebDefaultScriptDebugDelegate sharedScriptDebugDelegate] catchExceptions:_private->catchesDelegateExceptions];
1106 return _private->scriptDebugDelegateForwarder;
1109 - (void)_closeWindow
1111 [[self _UIDelegateForwarder] webViewClose:self];
1114 + (void)_unregisterViewClassAndRepresentationClassForMIMEType:(NSString *)MIMEType;
1116 [[WebFrameView _viewTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType];
1117 [[WebDataSource _repTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType];
1119 // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
1120 // in the WebCore MIMEType registry. For now we're doing this in a safe, limited manner
1121 // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
1122 MIMETypeRegistry::getSupportedNonImageMIMETypes().remove(MIMEType);
1125 + (void)_registerViewClass:(Class)viewClass representationClass:(Class)representationClass forURLScheme:(NSString *)URLScheme;
1127 NSString *MIMEType = [self _generatedMIMETypeForURLScheme:URLScheme];
1128 [self registerViewClass:viewClass representationClass:representationClass forMIMEType:MIMEType];
1130 // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
1131 // in the WebCore MIMEType registry. For now we're doing this in a safe, limited manner
1132 // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
1133 if ([viewClass class] == [WebHTMLView class])
1134 MIMETypeRegistry::getSupportedNonImageMIMETypes().add(MIMEType);
1136 // This is used to make _representationExistsForURLScheme faster.
1137 // Without this set, we'd have to create the MIME type each time.
1138 if (schemesWithRepresentationsSet == nil) {
1139 schemesWithRepresentationsSet = [[NSMutableSet alloc] init];
1141 [schemesWithRepresentationsSet addObject:[[[URLScheme lowercaseString] copy] autorelease]];
1144 + (NSString *)_generatedMIMETypeForURLScheme:(NSString *)URLScheme
1146 return [@"x-apple-web-kit/" stringByAppendingString:[URLScheme lowercaseString]];
1149 + (BOOL)_representationExistsForURLScheme:(NSString *)URLScheme
1151 return [schemesWithRepresentationsSet containsObject:[URLScheme lowercaseString]];
1154 + (BOOL)_canHandleRequest:(NSURLRequest *)request
1156 // FIXME: If <rdar://problem/5217309> gets fixed, this check can be removed
1160 if ([NSURLConnection canHandleRequest:request])
1163 NSString *scheme = [[request URL] scheme];
1165 if ([self _representationExistsForURLScheme:scheme])
1168 return ([scheme _webkit_isCaseInsensitiveEqualToString:@"applewebdata"]);
1171 + (NSString *)_decodeData:(NSData *)data
1173 HTMLNames::init(); // this method is used for importing bookmarks at startup, so HTMLNames are likely to be uninitialized yet
1174 RefPtr<TextResourceDecoder> decoder = new TextResourceDecoder("text/html"); // bookmark files are HTML
1175 String result = decoder->decode(static_cast<const char*>([data bytes]), [data length]);
1176 result += decoder->flush();
1180 - (void)_pushPerformingProgrammaticFocus
1182 _private->programmaticFocusCount++;
1185 - (void)_popPerformingProgrammaticFocus
1187 _private->programmaticFocusCount--;
1190 - (BOOL)_isPerformingProgrammaticFocus
1192 return _private->programmaticFocusCount != 0;
1195 - (void)_didChangeValueForKey: (NSString *)key
1197 LOG (Bindings, "calling didChangeValueForKey: %@", key);
1198 [self didChangeValueForKey: key];
1201 - (void)_willChangeValueForKey: (NSString *)key
1203 LOG (Bindings, "calling willChangeValueForKey: %@", key);
1204 [self willChangeValueForKey: key];
1207 + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key {
1208 static NSSet *manualNotifyKeys = nil;
1209 if (!manualNotifyKeys)
1210 manualNotifyKeys = [[NSSet alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey,
1211 _WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, _WebMainFrameDocumentKey, nil];
1212 if ([manualNotifyKeys containsObject:key])
1217 - (NSArray *)_declaredKeys {
1218 static NSArray *declaredKeys = nil;
1220 declaredKeys = [[NSArray alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey,
1221 _WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, _WebMainFrameDocumentKey, nil];
1222 return declaredKeys;
1225 - (void)setObservationInfo:(void *)info
1227 _private->observationInfo = info;
1230 - (void *)observationInfo
1232 return _private->observationInfo;
1235 - (void)_willChangeBackForwardKeys
1237 [self _willChangeValueForKey: _WebCanGoBackKey];
1238 [self _willChangeValueForKey: _WebCanGoForwardKey];
1241 - (void)_didChangeBackForwardKeys
1243 [self _didChangeValueForKey: _WebCanGoBackKey];
1244 [self _didChangeValueForKey: _WebCanGoForwardKey];
1247 - (void)_didStartProvisionalLoadForFrame:(WebFrame *)frame
1249 [self _willChangeBackForwardKeys];
1250 if (frame == [self mainFrame]){
1251 // Force an observer update by sending a will/did.
1252 [self _willChangeValueForKey: _WebIsLoadingKey];
1253 [self _didChangeValueForKey: _WebIsLoadingKey];
1255 [self _willChangeValueForKey: _WebMainFrameURLKey];
1258 [NSApp setWindowsNeedUpdate:YES];
1261 - (void)_didCommitLoadForFrame:(WebFrame *)frame
1263 if (frame == [self mainFrame])
1264 [self _didChangeValueForKey: _WebMainFrameURLKey];
1265 [NSApp setWindowsNeedUpdate:YES];
1268 - (void)_didFinishLoadForFrame:(WebFrame *)frame
1270 [self _didChangeBackForwardKeys];
1271 if (frame == [self mainFrame]){
1272 // Force an observer update by sending a will/did.
1273 [self _willChangeValueForKey: _WebIsLoadingKey];
1274 [self _didChangeValueForKey: _WebIsLoadingKey];
1276 [NSApp setWindowsNeedUpdate:YES];
1279 - (void)_didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
1281 [self _didChangeBackForwardKeys];
1282 if (frame == [self mainFrame]){
1283 // Force an observer update by sending a will/did.
1284 [self _willChangeValueForKey: _WebIsLoadingKey];
1285 [self _didChangeValueForKey: _WebIsLoadingKey];
1287 [NSApp setWindowsNeedUpdate:YES];
1290 - (void)_didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
1292 [self _didChangeBackForwardKeys];
1293 if (frame == [self mainFrame]){
1294 // Force an observer update by sending a will/did.
1295 [self _willChangeValueForKey: _WebIsLoadingKey];
1296 [self _didChangeValueForKey: _WebIsLoadingKey];
1298 [self _didChangeValueForKey: _WebMainFrameURLKey];
1300 [NSApp setWindowsNeedUpdate:YES];
1303 - (NSCachedURLResponse *)_cachedResponseForURL:(NSURL *)URL
1305 NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:URL];
1306 [request _web_setHTTPUserAgent:[self userAgentForURL:URL]];
1307 NSCachedURLResponse *cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:request];
1309 return cachedResponse;
1312 - (void)_writeImageForElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
1314 NSURL *linkURL = [element objectForKey:WebElementLinkURLKey];
1315 DOMElement *domElement = [element objectForKey:WebElementDOMNodeKey];
1316 [pasteboard _web_writeImage:(NSImage *)(domElement ? nil : [element objectForKey:WebElementImageKey])
1318 URL:linkURL ? linkURL : (NSURL *)[element objectForKey:WebElementImageURLKey]
1319 title:[element objectForKey:WebElementImageAltStringKey]
1320 archive:[[element objectForKey:WebElementDOMNodeKey] webArchive]
1325 - (void)_writeLinkElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
1327 [pasteboard _web_writeURL:[element objectForKey:WebElementLinkURLKey]
1328 andTitle:[element objectForKey:WebElementLinkLabelKey]
1332 - (void)_setInitiatedDrag:(BOOL)initiatedDrag
1334 if (!_private->page)
1336 _private->page->dragController()->setDidInitiateDrag(initiatedDrag);
1339 #if ENABLE(DASHBOARD_SUPPORT)
1341 #define DASHBOARD_CONTROL_LABEL @"control"
1343 - (void)_addScrollerDashboardRegions:(NSMutableDictionary *)regions from:(NSArray *)views
1345 // Add scroller regions for NSScroller and KWQScrollBar
1346 int i, count = [views count];
1348 for (i = 0; i < count; i++) {
1349 NSView *aView = [views objectAtIndex:i];
1351 if ([aView isKindOfClass:[NSScroller class]] ||
1352 [aView isKindOfClass:NSClassFromString (@"KWQScrollBar")]) {
1353 NSRect bounds = [aView bounds];
1354 NSRect adjustedBounds;
1355 adjustedBounds.origin = [self convertPoint:bounds.origin fromView:aView];
1356 adjustedBounds.origin.y = [self bounds].size.height - adjustedBounds.origin.y;
1358 // AppKit has horrible hack of placing absent scrollers at -100,-100
1359 if (adjustedBounds.origin.y == -100)
1361 adjustedBounds.size = bounds.size;
1362 NSRect clip = [aView visibleRect];
1363 NSRect adjustedClip;
1364 adjustedClip.origin = [self convertPoint:clip.origin fromView:aView];
1365 adjustedClip.origin.y = [self bounds].size.height - adjustedClip.origin.y;
1366 adjustedClip.size = clip.size;
1367 WebDashboardRegion *aRegion =
1368 [[[WebDashboardRegion alloc] initWithRect:adjustedBounds
1369 clip:adjustedClip type:WebDashboardRegionTypeScrollerRectangle] autorelease];
1370 NSMutableArray *scrollerRegions;
1371 scrollerRegions = [regions objectForKey:DASHBOARD_CONTROL_LABEL];
1372 if (!scrollerRegions) {
1373 scrollerRegions = [NSMutableArray array];
1374 [regions setObject:scrollerRegions forKey:DASHBOARD_CONTROL_LABEL];
1376 [scrollerRegions addObject:aRegion];
1378 [self _addScrollerDashboardRegions:regions from:[aView subviews]];
1382 - (void)_addScrollerDashboardRegions:(NSMutableDictionary *)regions
1384 [self _addScrollerDashboardRegions:regions from:[self subviews]];
1387 - (NSDictionary *)_dashboardRegions
1389 // Only return regions from main frame.
1390 Frame* mainFrame = core([self mainFrame]);
1393 NSMutableDictionary *regions = mainFrame->dashboardRegionsDictionary();
1394 [self _addScrollerDashboardRegions:regions];
1398 - (void)_setDashboardBehavior:(WebDashboardBehavior)behavior to:(BOOL)flag
1400 // FIXME: Remove this blanket assignment once Dashboard and Dashcode implement
1401 // specific support for the backward compatibility mode flag.
1402 if (behavior == WebDashboardBehaviorAllowWheelScrolling && flag == NO && _private->page)
1403 _private->page->settings()->setUsesDashboardBackwardCompatibilityMode(true);
1406 case WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows: {
1407 _private->dashboardBehaviorAlwaysSendMouseEventsToAllWindows = flag;
1410 case WebDashboardBehaviorAlwaysSendActiveNullEventsToPlugIns: {
1411 _private->dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns = flag;
1414 case WebDashboardBehaviorAlwaysAcceptsFirstMouse: {
1415 _private->dashboardBehaviorAlwaysAcceptsFirstMouse = flag;
1418 case WebDashboardBehaviorAllowWheelScrolling: {
1419 _private->dashboardBehaviorAllowWheelScrolling = flag;
1422 case WebDashboardBehaviorUseBackwardCompatibilityMode: {
1424 _private->page->settings()->setUsesDashboardBackwardCompatibilityMode(flag);
1430 - (BOOL)_dashboardBehavior:(WebDashboardBehavior)behavior
1433 case WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows: {
1434 return _private->dashboardBehaviorAlwaysSendMouseEventsToAllWindows;
1436 case WebDashboardBehaviorAlwaysSendActiveNullEventsToPlugIns: {
1437 return _private->dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns;
1439 case WebDashboardBehaviorAlwaysAcceptsFirstMouse: {
1440 return _private->dashboardBehaviorAlwaysAcceptsFirstMouse;
1442 case WebDashboardBehaviorAllowWheelScrolling: {
1443 return _private->dashboardBehaviorAllowWheelScrolling;
1445 case WebDashboardBehaviorUseBackwardCompatibilityMode: {
1446 return _private->page && _private->page->settings()->usesDashboardBackwardCompatibilityMode();
1452 #endif /* ENABLE(DASHBOARD_SUPPORT) */
1454 + (void)_setShouldUseFontSmoothing:(BOOL)f
1456 WebCoreSetShouldUseFontSmoothing(f);
1459 + (BOOL)_shouldUseFontSmoothing
1461 return WebCoreShouldUseFontSmoothing();
1464 + (void)_setUsesTestModeFocusRingColor:(BOOL)f
1466 setUsesTestModeFocusRingColor(f);
1469 + (BOOL)_usesTestModeFocusRingColor
1471 return usesTestModeFocusRingColor();
1474 // This is only used by versions of Safari up to and including 3.0 and should be removed in a future release.
1475 + (NSString *)_minimumRequiredSafariBuildNumber
1480 - (void)setAlwaysShowVerticalScroller:(BOOL)flag
1482 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
1484 [scrollview setVerticalScrollingMode:ScrollbarAlwaysOn andLock:YES];
1486 [scrollview setVerticalScrollingModeLocked:NO];
1487 [scrollview setVerticalScrollingMode:ScrollbarAuto];
1491 - (BOOL)alwaysShowVerticalScroller
1493 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
1494 return [scrollview verticalScrollingModeLocked] && [scrollview verticalScrollingMode] == ScrollbarAlwaysOn;
1497 - (void)setAlwaysShowHorizontalScroller:(BOOL)flag
1499 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
1501 [scrollview setHorizontalScrollingMode:ScrollbarAlwaysOn andLock:YES];
1503 [scrollview setHorizontalScrollingModeLocked:NO];
1504 [scrollview setHorizontalScrollingMode:ScrollbarAuto];
1508 - (void)setProhibitsMainFrameScrolling:(BOOL)prohibits
1510 Frame* mainFrame = core([self mainFrame]);
1512 mainFrame->setProhibitsScrolling(prohibits);
1515 - (BOOL)alwaysShowHorizontalScroller
1517 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
1518 return [scrollview horizontalScrollingModeLocked] && [scrollview horizontalScrollingMode] == ScrollbarAlwaysOn;
1521 - (void)_setInViewSourceMode:(BOOL)flag
1523 Frame* mainFrame = core([self mainFrame]);
1525 mainFrame->setInViewSourceMode(flag);
1528 - (BOOL)_inViewSourceMode
1530 Frame* mainFrame = core([self mainFrame]);
1531 return mainFrame && mainFrame->inViewSourceMode();
1534 - (void)_setUseFastImageScalingMode:(BOOL)flag
1536 if (_private->page && _private->page->inLowQualityImageInterpolationMode() != flag) {
1537 _private->page->setInLowQualityImageInterpolationMode(flag);
1538 [self setNeedsDisplay:YES];
1542 - (BOOL)_inFastImageScalingMode
1545 return _private->page->inLowQualityImageInterpolationMode();
1549 - (void)_setAdditionalWebPlugInPaths:(NSArray *)newPaths
1551 if (!_private->pluginDatabase)
1552 _private->pluginDatabase = [[WebPluginDatabase alloc] init];
1554 [_private->pluginDatabase setPlugInPaths:newPaths];
1555 [_private->pluginDatabase refresh];
1558 - (void)_attachScriptDebuggerToAllFrames
1560 for (Frame* frame = core([self mainFrame]); frame; frame = frame->tree()->traverseNext())
1561 [kit(frame) _attachScriptDebugger];
1564 - (void)_detachScriptDebuggerFromAllFrames
1566 for (Frame* frame = core([self mainFrame]); frame; frame = frame->tree()->traverseNext())
1567 [kit(frame) _detachScriptDebugger];
1570 - (void)setBackgroundColor:(NSColor *)backgroundColor
1572 if ([_private->backgroundColor isEqual:backgroundColor])
1575 id old = _private->backgroundColor;
1576 _private->backgroundColor = [backgroundColor retain];
1579 [[self mainFrame] _updateBackground];
1582 - (NSColor *)backgroundColor
1584 return _private->backgroundColor;
1587 - (BOOL)defersCallbacks
1589 if (!_private->page)
1591 return _private->page->defersLoading();
1594 - (void)setDefersCallbacks:(BOOL)defer
1596 if (!_private->page)
1598 return _private->page->setDefersLoading(defer);
1601 // For backwards compatibility with the WebBackForwardList API, we honor both
1602 // a per-WebView and a per-preferences setting for whether to use the page cache.
1604 - (BOOL)usesPageCache
1606 return _private->usesPageCache && [[self preferences] usesPageCache];
1609 - (void)setUsesPageCache:(BOOL)usesPageCache
1611 _private->usesPageCache = usesPageCache;
1613 // Post a notification so the WebCore settings update.
1614 [[self preferences] _postPreferencesChangesNotification];
1617 - (void)handleAuthenticationForResource:(id)identifier challenge:(NSURLAuthenticationChallenge *)challenge fromDataSource:(WebDataSource *)dataSource
1619 NSWindow *window = [self hostWindow] ? [self hostWindow] : [self window];
1620 [[WebPanelAuthenticationHandler sharedHandler] startAuthentication:challenge window:window];
1623 - (void)_clearUndoRedoOperations
1625 if (!_private->page)
1627 _private->page->clearUndoRedoOperations();
1630 - (void)_setCatchesDelegateExceptions:(BOOL)f
1632 _private->catchesDelegateExceptions = f;
1635 - (BOOL)_catchesDelegateExceptions
1637 return _private->catchesDelegateExceptions;
1640 - (void)_executeCoreCommandByName:(NSString *)name value:(NSString *)value
1642 Frame* coreFrame = core([self mainFrame]);
1645 coreFrame->editor()->command(name).execute(value);
1650 @implementation _WebSafeForwarder
1652 // Used to send messages to delegates that implement informal protocols.
1654 - (id)initWithTarget:(id)t defaultTarget:(id)dt catchExceptions:(BOOL)c
1656 self = [super init];
1659 target = t; // Non retained.
1661 catchExceptions = c;
1665 - (void)forwardInvocation:(NSInvocation *)invocation
1667 if ([target respondsToSelector:[invocation selector]]) {
1668 if (catchExceptions) {
1670 [invocation invokeWithTarget:target];
1671 } @catch(id exception) {
1672 ReportDiscardedDelegateException([invocation selector], exception);
1675 [invocation invokeWithTarget:target];
1679 if ([defaultTarget respondsToSelector:[invocation selector]])
1680 [invocation invokeWithTarget:defaultTarget];
1682 // Do nothing quietly if method not implemented.
1685 - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
1687 return [defaultTarget methodSignatureForSelector:aSelector];
1692 @implementation WebView
1696 static BOOL initialized = NO;
1701 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_applicationWillTerminate) name:NSApplicationWillTerminateNotification object:NSApp];
1702 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:) name:WebPreferencesChangedNotification object:nil];
1703 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesRemovedNotification:) name:WebPreferencesRemovedNotification object:nil];
1706 + (void)_applicationWillTerminate
1708 applicationIsTerminating = YES;
1709 if (!pluginDatabaseClientCount)
1710 [WebPluginDatabase closeSharedDatabase];
1712 PageGroup::closeLocalStorage();
1715 + (BOOL)canShowMIMEType:(NSString *)MIMEType
1717 return [self _viewClass:nil andRepresentationClass:nil forMIMEType:MIMEType];
1720 - (WebBasePluginPackage *)_pluginForMIMEType:(NSString *)MIMEType
1722 WebBasePluginPackage *pluginPackage = [[WebPluginDatabase sharedDatabase] pluginForMIMEType:MIMEType];
1724 return pluginPackage;
1726 if (_private->pluginDatabase)
1727 return [_private->pluginDatabase pluginForMIMEType:MIMEType];
1732 - (WebBasePluginPackage *)_pluginForExtension:(NSString *)extension
1734 WebBasePluginPackage *pluginPackage = [[WebPluginDatabase sharedDatabase] pluginForExtension:extension];
1736 return pluginPackage;
1738 if (_private->pluginDatabase)
1739 return [_private->pluginDatabase pluginForExtension:extension];
1744 - (BOOL)_isMIMETypeRegisteredAsPlugin:(NSString *)MIMEType
1746 if ([[WebPluginDatabase sharedDatabase] isMIMETypeRegistered:MIMEType])
1749 if (_private->pluginDatabase && [_private->pluginDatabase isMIMETypeRegistered:MIMEType])
1755 + (BOOL)canShowMIMETypeAsHTML:(NSString *)MIMEType
1757 return [WebFrameView _canShowMIMETypeAsHTML:MIMEType];
1760 + (NSArray *)MIMETypesShownAsHTML
1762 NSMutableDictionary *viewTypes = [WebFrameView _viewTypesAllowImageTypeOmission:YES];
1763 NSEnumerator *enumerator = [viewTypes keyEnumerator];
1765 NSMutableArray *array = [[[NSMutableArray alloc] init] autorelease];
1767 while ((key = [enumerator nextObject])) {
1768 if ([viewTypes objectForKey:key] == [WebHTMLView class])
1769 [array addObject:key];
1775 + (void)setMIMETypesShownAsHTML:(NSArray *)MIMETypes
1777 NSDictionary *viewTypes = [[WebFrameView _viewTypesAllowImageTypeOmission:YES] copy];
1778 NSEnumerator *enumerator = [viewTypes keyEnumerator];
1780 while ((key = [enumerator nextObject])) {
1781 if ([viewTypes objectForKey:key] == [WebHTMLView class])
1782 [WebView _unregisterViewClassAndRepresentationClassForMIMEType:key];
1785 int i, count = [MIMETypes count];
1786 for (i = 0; i < count; i++) {
1787 [WebView registerViewClass:[WebHTMLView class]
1788 representationClass:[WebHTMLRepresentation class]
1789 forMIMEType:[MIMETypes objectAtIndex:i]];
1791 [viewTypes release];
1794 + (NSURL *)URLFromPasteboard:(NSPasteboard *)pasteboard
1796 return [pasteboard _web_bestURL];
1799 + (NSString *)URLTitleFromPasteboard:(NSPasteboard *)pasteboard
1801 return [pasteboard stringForType:WebURLNamePboardType];
1804 + (void)registerURLSchemeAsLocal:(NSString *)protocol
1806 FrameLoader::registerURLSchemeAsLocal(protocol);
1809 - (void)_registerDraggedTypes
1811 NSArray *editableTypes = [WebHTMLView _insertablePasteboardTypes];
1812 NSArray *URLTypes = [NSPasteboard _web_dragTypesForURL];
1813 NSMutableSet *types = [[NSMutableSet alloc] initWithArray:editableTypes];
1814 [types addObjectsFromArray:URLTypes];
1815 [self registerForDraggedTypes:[types allObjects]];
1819 static void WebKitInitializeApplicationCachePathIfNecessary()
1821 static BOOL initialized = NO;
1825 NSString *appName = [[NSBundle mainBundle] bundleIdentifier];
1827 appName = [[NSProcessInfo processInfo] processName];
1831 NSString* cacheDir = nil;
1833 #ifdef BUILDING_ON_TIGER
1834 cacheDir = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Caches"];
1836 char cacheDirectory[MAXPATHLEN];
1837 size_t cacheDirectoryLen = confstr(_CS_DARWIN_USER_CACHE_DIR, cacheDirectory, MAXPATHLEN);
1839 if (cacheDirectoryLen)
1840 cacheDir = [[NSFileManager defaultManager] stringWithFileSystemRepresentation:cacheDirectory length:cacheDirectoryLen - 1];
1843 cacheDir = [cacheDir stringByAppendingPathComponent:appName];
1845 cacheStorage().setCacheDirectory(cacheDir);
1849 - (void)_commonInitializationWithFrameName:(NSString *)frameName groupName:(NSString *)groupName
1851 WebPreferences *standardPreferences = [WebPreferences standardPreferences];
1852 [standardPreferences willAddToWebView];
1854 _private->preferences = [standardPreferences retain];
1855 _private->catchesDelegateExceptions = YES;
1856 _private->mainFrameDocumentReady = NO;
1857 _private->drawsBackground = YES;
1858 _private->smartInsertDeleteEnabled = YES;
1859 _private->backgroundColor = [[NSColor whiteColor] retain];
1861 NSRect f = [self frame];
1862 WebFrameView *frameView = [[WebFrameView alloc] initWithFrame: NSMakeRect(0,0,f.size.width,f.size.height)];
1863 [frameView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
1864 [self addSubview:frameView];
1865 [frameView release];
1867 WebKitInitializeLoggingChannelsIfNecessary();
1868 WebCore::InitializeLoggingChannelsIfNecessary();
1869 [WebHistoryItem initWindowWatcherIfNecessary];
1870 WebKitInitializeDatabasesIfNecessary();
1871 WebKitInitializeApplicationCachePathIfNecessary();
1873 _private->page = new Page(new WebChromeClient(self), new WebContextMenuClient(self), new WebEditorClient(self), new WebDragClient(self), new WebInspectorClient(self));
1875 [WebFrame _createMainFrameWithPage:_private->page frameName:frameName frameView:frameView];
1877 #ifndef BUILDING_ON_TIGER
1878 if (WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_LOADING_DURING_COMMON_RUNLOOP_MODES))
1879 [self scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
1881 [self scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
1884 [self _addToAllWebViewsSet];
1885 [self setGroupName:groupName];
1887 // If there's already a next key view (e.g., from a nib), wire it up to our
1888 // contained frame view. In any case, wire our next key view up to the our
1889 // contained frame view. This works together with our becomeFirstResponder
1890 // and setNextKeyView overrides.
1891 NSView *nextKeyView = [self nextKeyView];
1892 if (nextKeyView && nextKeyView != frameView)
1893 [frameView setNextKeyView:nextKeyView];
1894 [super setNextKeyView:frameView];
1898 [self _registerDraggedTypes];
1900 // initialize WebScriptDebugServer here so listeners can register before any pages are loaded.
1901 if ([WebView _scriptDebuggerEnabled])
1902 [WebScriptDebugServer sharedScriptDebugServer];
1904 WebPreferences *prefs = [self preferences];
1905 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:)
1906 name:WebPreferencesChangedNotification object:prefs];
1908 // Post a notification so the WebCore settings update.
1909 [[self preferences] _postPreferencesChangesNotification];
1912 if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_LOCAL_RESOURCE_SECURITY_RESTRICTION))
1913 FrameLoader::setRestrictAccessToLocal(false);
1916 - (id)initWithFrame:(NSRect)f
1918 return [self initWithFrame:f frameName:nil groupName:nil];
1921 - (id)initWithFrame:(NSRect)f frameName:(NSString *)frameName groupName:(NSString *)groupName;
1923 self = [super initWithFrame:f];
1927 #ifdef ENABLE_WEBKIT_UNSET_DYLD_FRAMEWORK_PATH
1928 // DYLD_FRAMEWORK_PATH is used so Safari will load the development version of WebKit, which
1929 // may not work with other WebKit applications. Unsetting DYLD_FRAMEWORK_PATH removes the
1930 // need for Safari to unset it to prevent it from being passed to applications it launches.
1931 // Unsetting it when a WebView is first created is as good a place as any.
1932 // See <http://bugs.webkit.org/show_bug.cgi?id=4286> for more details.
1933 if (getenv("WEBKIT_UNSET_DYLD_FRAMEWORK_PATH")) {
1934 unsetenv("DYLD_FRAMEWORK_PATH");
1935 unsetenv("WEBKIT_UNSET_DYLD_FRAMEWORK_PATH");
1939 _private = [[WebViewPrivate alloc] init];
1940 [self _commonInitializationWithFrameName:frameName groupName:groupName];
1941 [self setMaintainsBackForwardList: YES];
1945 - (id)initWithCoder:(NSCoder *)decoder
1947 WebView *result = nil;
1950 NSString *frameName;
1951 NSString *groupName;
1952 WebPreferences *preferences;
1953 BOOL useBackForwardList = NO;
1954 BOOL allowsUndo = YES;
1956 result = [super initWithCoder:decoder];
1957 result->_private = [[WebViewPrivate alloc] init];
1959 // We don't want any of the archived subviews. The subviews will always
1960 // be created in _commonInitializationFrameName:groupName:.
1961 [[result subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
1963 if ([decoder allowsKeyedCoding]) {
1964 frameName = [decoder decodeObjectForKey:@"FrameName"];
1965 groupName = [decoder decodeObjectForKey:@"GroupName"];
1966 preferences = [decoder decodeObjectForKey:@"Preferences"];
1967 useBackForwardList = [decoder decodeBoolForKey:@"UseBackForwardList"];
1968 if ([decoder containsValueForKey:@"AllowsUndo"])
1969 allowsUndo = [decoder decodeBoolForKey:@"AllowsUndo"];
1972 [decoder decodeValueOfObjCType:@encode(int) at:&version];
1973 frameName = [decoder decodeObject];
1974 groupName = [decoder decodeObject];
1975 preferences = [decoder decodeObject];
1977 [decoder decodeValuesOfObjCTypes:"c", &useBackForwardList];
1978 // The allowsUndo field is no longer written out in encodeWithCoder, but since there are
1979 // version 3 NIBs that have this field encoded, we still need to read it in.
1981 [decoder decodeValuesOfObjCTypes:"c", &allowsUndo];
1984 if (![frameName isKindOfClass:[NSString class]])
1986 if (![groupName isKindOfClass:[NSString class]])
1988 if (![preferences isKindOfClass:[WebPreferences class]])
1991 LOG(Encoding, "FrameName = %@, GroupName = %@, useBackForwardList = %d\n", frameName, groupName, (int)useBackForwardList);
1992 [result _commonInitializationWithFrameName:frameName groupName:groupName];
1993 [result page]->backForwardList()->setEnabled(useBackForwardList);
1994 result->_private->allowsUndo = allowsUndo;
1996 [result setPreferences:preferences];
1997 } @catch (NSException *localException) {
2005 - (void)encodeWithCoder:(NSCoder *)encoder
2007 // Set asside the subviews before we archive. We don't want to archive any subviews.
2008 // The subviews will always be created in _commonInitializationFrameName:groupName:.
2009 id originalSubviews = _subviews;
2012 [super encodeWithCoder:encoder];
2014 // Restore the subviews we set aside.
2015 _subviews = originalSubviews;
2017 BOOL useBackForwardList = _private->page && _private->page->backForwardList()->enabled();
2018 if ([encoder allowsKeyedCoding]) {
2019 [encoder encodeObject:[[self mainFrame] name] forKey:@"FrameName"];
2020 [encoder encodeObject:[self groupName] forKey:@"GroupName"];
2021 [encoder encodeObject:[self preferences] forKey:@"Preferences"];
2022 [encoder encodeBool:useBackForwardList forKey:@"UseBackForwardList"];
2023 [encoder encodeBool:_private->allowsUndo forKey:@"AllowsUndo"];
2025 int version = WebViewVersion;
2026 [encoder encodeValueOfObjCType:@encode(int) at:&version];
2027 [encoder encodeObject:[[self mainFrame] name]];
2028 [encoder encodeObject:[self groupName]];
2029 [encoder encodeObject:[self preferences]];
2030 [encoder encodeValuesOfObjCTypes:"c", &useBackForwardList];
2031 // DO NOT encode any new fields here, doing so will break older WebKit releases.
2034 LOG(Encoding, "FrameName = %@, GroupName = %@, useBackForwardList = %d\n", [[self mainFrame] name], [self groupName], (int)useBackForwardList);
2039 // call close to ensure we tear-down completely
2040 // this maintains our old behavior for existing applications
2046 // [super dealloc] can end up dispatching against _private (3466082)
2054 ASSERT(_private->closed);
2066 - (void)setShouldCloseWithWindow:(BOOL)close
2068 _private->shouldCloseWithWindow = close;
2071 - (BOOL)shouldCloseWithWindow
2073 return _private->shouldCloseWithWindow;
2076 - (void)viewWillMoveToWindow:(NSWindow *)window
2078 // Don't do anything if the WebView isn't initialized.
2079 // This happens when decoding a WebView in a nib.
2080 // FIXME: What sets up the observer of NSWindowWillCloseNotification in this case?
2084 if (_private->closed)
2087 if ([self window] && [self window] != [self hostWindow])
2088 [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowWillCloseNotification object:[self window]];
2091 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillClose:) name:NSWindowWillCloseNotification object:window];
2093 // Ensure that we will receive the events that WebHTMLView (at least) needs.
2094 // The following are expensive enough that we don't want to call them over
2095 // and over, so do them when we move into a window.
2096 [window setAcceptsMouseMovedEvents:YES];
2097 WKSetNSWindowShouldPostEventNotifications(window, YES);
2101 - (void)_windowWillClose:(NSNotification *)notification
2103 if ([self shouldCloseWithWindow] && ([self window] == [self hostWindow] || ([self window] && ![self hostWindow]) || (![self window] && [self hostWindow])))
2107 - (void)setPreferences:(WebPreferences *)prefs
2110 prefs = [WebPreferences standardPreferences];
2112 if (_private->preferences == prefs)
2115 [prefs willAddToWebView];
2117 WebPreferences *oldPrefs = _private->preferences;
2119 [[NSNotificationCenter defaultCenter] removeObserver:self name:WebPreferencesChangedNotification object:[self preferences]];
2120 [WebPreferences _removeReferenceForIdentifier:[oldPrefs identifier]];
2122 _private->preferences = [prefs retain];
2124 // After registering for the notification, post it so the WebCore settings update.
2125 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:)
2126 name:WebPreferencesChangedNotification object:[self preferences]];
2127 [[self preferences] _postPreferencesChangesNotification];
2129 [oldPrefs didRemoveFromWebView];
2133 - (WebPreferences *)preferences
2135 return _private->preferences;
2138 - (void)setPreferencesIdentifier:(NSString *)anIdentifier
2140 if (!_private->closed && ![anIdentifier isEqual:[[self preferences] identifier]]) {
2141 WebPreferences *prefs = [[WebPreferences alloc] initWithIdentifier:anIdentifier];
2142 [self setPreferences:prefs];
2147 - (NSString *)preferencesIdentifier
2149 return [[self preferences] identifier];
2153 - (void)setUIDelegate:delegate
2155 _private->UIDelegate = delegate;
2156 [_private->UIDelegateForwarder release];
2157 _private->UIDelegateForwarder = nil;
2162 return _private->UIDelegate;
2165 - (void)setResourceLoadDelegate: delegate
2167 _private->resourceProgressDelegate = delegate;
2168 [self _cacheResourceLoadDelegateImplementations];
2171 - resourceLoadDelegate
2173 return _private->resourceProgressDelegate;
2176 - (void)setDownloadDelegate: delegate
2178 _private->downloadDelegate = delegate;
2184 return _private->downloadDelegate;
2187 - (void)setPolicyDelegate:delegate
2189 _private->policyDelegate = delegate;
2190 [_private->policyDelegateForwarder release];
2191 _private->policyDelegateForwarder = nil;
2196 return _private->policyDelegate;
2199 - (void)setFrameLoadDelegate:delegate
2201 _private->frameLoadDelegate = delegate;
2202 [self _cacheFrameLoadDelegateImplementations];
2204 // If this delegate wants callbacks for icons, fire up the icon database.
2205 if (_private->frameLoadDelegateImplementations.didReceiveIconForFrameFunc)
2206 [WebIconDatabase sharedIconDatabase];
2211 return _private->frameLoadDelegate;
2214 - (WebFrame *)mainFrame
2216 // This can be called in initialization, before _private has been set up (3465613)
2219 if (!_private->page)
2221 return kit(_private->page->mainFrame());
2224 - (WebFrame *)selectedFrame
2226 // If the first responder is a view in our tree, we get the frame containing the first responder.
2227 // This is faster than searching the frame hierarchy, and will give us a result even in the case
2228 // where the focused frame doesn't actually contain a selection.
2229 WebFrame *focusedFrame = [self _focusedFrame];
2231 return focusedFrame;
2233 // If the first responder is outside of our view tree, we search for a frame containing a selection.
2234 // There should be at most only one of these.
2235 return [[self mainFrame] _findFrameWithSelection];
2238 - (WebBackForwardList *)backForwardList
2240 if (!_private->page)
2242 if (!_private->page->backForwardList()->enabled())
2244 return kit(_private->page->backForwardList());
2247 - (void)setMaintainsBackForwardList: (BOOL)flag
2249 if (!_private->page)
2251 _private->page->backForwardList()->setEnabled(flag);
2256 if (!_private->page)
2259 return _private->page->goBack();
2264 if (!_private->page)
2267 return _private->page->goForward();
2270 - (BOOL)goToBackForwardItem:(WebHistoryItem *)item
2272 if (!_private->page)
2275 _private->page->goToItem(core(item), FrameLoadTypeIndexedBackForward);
2279 - (void)setTextSizeMultiplier:(float)m
2281 [self _setZoomMultiplier:m isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
2284 - (float)textSizeMultiplier
2286 return _private->zoomMultiplierIsTextOnly ? _private->zoomMultiplier : 1.0f;
2289 - (void)_setZoomMultiplier:(float)m isTextOnly:(BOOL)isTextOnly
2291 // NOTE: This has no visible effect when viewing a PDF (see <rdar://problem/4737380>)
2292 _private->zoomMultiplier = m;
2293 _private->zoomMultiplierIsTextOnly = isTextOnly;
2294 Frame* coreFrame = core([self mainFrame]);
2296 coreFrame->setZoomFactor(m, isTextOnly);
2299 - (float)_zoomMultiplier:(BOOL)isTextOnly
2301 if (isTextOnly != _private->zoomMultiplierIsTextOnly)
2303 return _private->zoomMultiplier;
2306 - (float)_realZoomMultiplier
2308 return _private->zoomMultiplier;
2311 - (BOOL)_realZoomMultiplierIsTextOnly
2313 return _private->zoomMultiplierIsTextOnly;
2316 #define MinimumZoomMultiplier 0.5f
2317 #define MaximumZoomMultiplier 3.0f
2318 #define ZoomMultiplierRatio 1.2f
2320 - (BOOL)_canZoomOut:(BOOL)isTextOnly
2322 id docView = [[[self mainFrame] frameView] documentView];
2323 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
2324 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
2325 return [zoomingDocView _canZoomOut];
2327 return [self _zoomMultiplier:isTextOnly] / ZoomMultiplierRatio > MinimumZoomMultiplier;
2331 - (BOOL)_canZoomIn:(BOOL)isTextOnly
2333 id docView = [[[self mainFrame] frameView] documentView];
2334 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
2335 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
2336 return [zoomingDocView _canZoomIn];
2338 return [self _zoomMultiplier:isTextOnly] * ZoomMultiplierRatio < MaximumZoomMultiplier;
2341 - (IBAction)_zoomOut:(id)sender isTextOnly:(BOOL)isTextOnly
2343 id docView = [[[self mainFrame] frameView] documentView];
2344 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
2345 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
2346 return [zoomingDocView _zoomOut:sender];
2348 float newScale = [self _zoomMultiplier:isTextOnly] / ZoomMultiplierRatio;
2349 if (newScale > MinimumZoomMultiplier)
2350 [self _setZoomMultiplier:newScale isTextOnly:isTextOnly];
2353 - (IBAction)_zoomIn:(id)sender isTextOnly:(BOOL)isTextOnly
2355 id docView = [[[self mainFrame] frameView] documentView];
2356 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
2357 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
2358 return [zoomingDocView _zoomIn:sender];
2360 float newScale = [self _zoomMultiplier:isTextOnly] * ZoomMultiplierRatio;
2361 if (newScale < MaximumZoomMultiplier)
2362 [self _setZoomMultiplier:newScale isTextOnly:isTextOnly];
2365 - (BOOL)_canResetZoom:(BOOL)isTextOnly
2367 id docView = [[[self mainFrame] frameView] documentView];
2368 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
2369 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
2370 return [zoomingDocView _canResetZoom];
2372 return [self _zoomMultiplier:isTextOnly] != 1.0f;
2375 - (IBAction)_resetZoom:(id)sender isTextOnly:(BOOL)isTextOnly
2377 id docView = [[[self mainFrame] frameView] documentView];
2378 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
2379 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
2380 return [zoomingDocView _resetZoom:sender];
2382 if ([self _zoomMultiplier:isTextOnly] != 1.0f)
2383 [self _setZoomMultiplier:1.0f isTextOnly:isTextOnly];
2386 - (void)setApplicationNameForUserAgent:(NSString *)applicationName
2388 NSString *name = [applicationName copy];
2389 [_private->applicationNameForUserAgent release];
2390 _private->applicationNameForUserAgent = name;
2391 if (!_private->userAgentOverridden)
2392 *_private->userAgent = String();
2395 - (NSString *)applicationNameForUserAgent
2397 return [[_private->applicationNameForUserAgent retain] autorelease];
2400 - (void)setCustomUserAgent:(NSString *)userAgentString
2402 *_private->userAgent = userAgentString;
2403 _private->userAgentOverridden = userAgentString != nil;
2406 - (NSString *)customUserAgent
2408 if (!_private->userAgentOverridden)
2410 return *_private->userAgent;
2413 - (void)setMediaStyle:(NSString *)mediaStyle
2415 if (_private->mediaStyle != mediaStyle) {
2416 [_private->mediaStyle release];
2417 _private->mediaStyle = [mediaStyle copy];
2421 - (NSString *)mediaStyle
2423 return _private->mediaStyle;
2426 - (BOOL)supportsTextEncoding
2428 id documentView = [[[self mainFrame] frameView] documentView];
2429 return [documentView conformsToProtocol:@protocol(WebDocumentText)]
2430 && [documentView supportsTextEncoding];
2433 - (void)setCustomTextEncodingName:(NSString *)encoding
2435 NSString *oldEncoding = [self customTextEncodingName];
2436 if (encoding == oldEncoding || [encoding isEqualToString:oldEncoding])
2438 if (Frame* mainFrame = core([self mainFrame]))
2439 mainFrame->loader()->reloadAllowingStaleData(encoding);
2442 - (NSString *)_mainFrameOverrideEncoding
2444 WebDataSource *dataSource = [[self mainFrame] provisionalDataSource];
2445 if (dataSource == nil)
2446 dataSource = [[self mainFrame] _dataSource];
2447 if (dataSource == nil)
2449 return nsStringNilIfEmpty([dataSource _documentLoader]->overrideEncoding());
2452 - (NSString *)customTextEncodingName
2454 return [self _mainFrameOverrideEncoding];
2457 - (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script
2459 // Return statements are only valid in a function but some applications pass in scripts
2460 // prefixed with return (<rdar://problems/5103720&4616860>) since older WebKit versions
2461 // silently ignored the return. If the application is linked against an earlier version
2462 // of WebKit we will strip the return so the script wont fail.
2463 if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_JAVASCRIPT_RETURN_QUIRK)) {
2464 NSRange returnStringRange = [script rangeOfString:@"return "];
2465 if (returnStringRange.length && !returnStringRange.location)
2466 script = [script substringFromIndex:returnStringRange.location + returnStringRange.length];
2469 NSString *result = [[self mainFrame] _stringByEvaluatingJavaScriptFromString:script];
2470 // The only way stringByEvaluatingJavaScriptFromString can return nil is if the frame was removed by the script
2471 // Since there's no way to get rid of the main frame, result will never ever be nil here.
2477 - (WebScriptObject *)windowScriptObject
2479 Frame* coreFrame = core([self mainFrame]);
2482 return coreFrame->windowScriptObject();
2485 // Get the appropriate user-agent string for a particular URL.
2486 - (NSString *)userAgentForURL:(NSURL *)url
2488 return [self _userAgentForURL:KURL([url absoluteURL])];
2491 - (void)setHostWindow:(NSWindow *)hostWindow
2493 if (_private->closed)
2495 if (hostWindow == _private->hostWindow)
2498 Frame* coreFrame = core([self mainFrame]);
2499 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
2500 [[[kit(frame) frameView] documentView] viewWillMoveToHostWindow:hostWindow];
2501 if (_private->hostWindow && [self window] != _private->hostWindow)
2502 [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowWillCloseNotification object:_private->hostWindow];
2504 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillClose:) name:NSWindowWillCloseNotification object:hostWindow];
2505 [_private->hostWindow release];
2506 _private->hostWindow = [hostWindow retain];
2507 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
2508 [[[kit(frame) frameView] documentView] viewDidMoveToHostWindow];
2511 - (NSWindow *)hostWindow
2513 return _private->hostWindow;
2516 - (NSView <WebDocumentView> *)documentViewAtWindowPoint:(NSPoint)point
2518 return [[self _frameViewAtWindowPoint:point] documentView];
2521 - (NSDictionary *)_elementAtWindowPoint:(NSPoint)windowPoint
2523 WebFrameView *frameView = [self _frameViewAtWindowPoint:windowPoint];
2526 NSView <WebDocumentView> *documentView = [frameView documentView];
2527 if ([documentView conformsToProtocol:@protocol(WebDocumentElement)]) {
2528 NSPoint point = [documentView convertPoint:windowPoint fromView:nil];
2529 return [(NSView <WebDocumentElement> *)documentView elementAtPoint:point];
2531 return [NSDictionary dictionaryWithObject:[frameView webFrame] forKey:WebElementFrameKey];
2534 - (NSDictionary *)elementAtPoint:(NSPoint)point
2536 return [self _elementAtWindowPoint:[self convertPoint:point toView:nil]];
2539 // The following 2 internal NSView methods are called on the drag destination by make scrolling while dragging work.
2540 // Scrolling while dragging will only work if the drag destination is in a scroll view. The WebView is the drag destination.
2541 // When dragging to a WebView, the document subview should scroll, but it doesn't because it is not the drag destination.
2542 // Forward these calls to the document subview to make its scroll view scroll.
2543 - (void)_autoscrollForDraggingInfo:(id)draggingInfo timeDelta:(NSTimeInterval)repeatDelta
2545 NSView <WebDocumentView> *documentView = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
2546 [documentView _autoscrollForDraggingInfo:draggingInfo timeDelta:repeatDelta];
2549 - (BOOL)_shouldAutoscrollForDraggingInfo:(id)draggingInfo
2551 NSView <WebDocumentView> *documentView = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
2552 return [documentView _shouldAutoscrollForDraggingInfo:draggingInfo];
2555 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)draggingInfo
2557 NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
2558 WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]] ? (WebHTMLView*)view : nil);
2559 IntPoint client([draggingInfo draggingLocation]);
2560 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
2561 DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
2562 return core(self)->dragController()->dragEntered(&dragData);
2565 - (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)draggingInfo
2567 Page* page = core(self);
2569 return NSDragOperationNone;
2571 NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
2572 WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]] ? (WebHTMLView*)view : nil);
2573 IntPoint client([draggingInfo draggingLocation]);
2574 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
2575 DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
2576 return page->dragController()->dragUpdated(&dragData);
2579 - (void)draggingExited:(id <NSDraggingInfo>)draggingInfo
2581 Page* page = core(self);
2585 NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
2586 WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]] ? (WebHTMLView*)view : nil);
2587 IntPoint client([draggingInfo draggingLocation]);
2588 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
2589 DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
2590 page->dragController()->dragExited(&dragData);
2593 - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)draggingInfo
2598 - (BOOL)performDragOperation:(id <NSDraggingInfo>)draggingInfo
2600 NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
2601 WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]]? (WebHTMLView*)view : nil);
2602 IntPoint client([draggingInfo draggingLocation]);
2603 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
2604 DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
2605 return core(self)->dragController()->performDrag(&dragData);
2608 - (NSView *)_hitTest:(NSPoint *)aPoint dragTypes:(NSSet *)types
2610 NSView *hitView = [super _hitTest:aPoint dragTypes:types];
2611 if (!hitView && [[self superview] mouse:*aPoint inRect:[self frame]]) {
2618 - (BOOL)acceptsFirstResponder
2620 return [[[self mainFrame] frameView] acceptsFirstResponder];
2623 - (BOOL)becomeFirstResponder
2625 if (_private->becomingFirstResponder) {
2626 // Fix for unrepro infinite recursion reported in radar 4448181. If we hit this assert on
2627 // a debug build, we should figure out what causes the problem and do a better fix.
2628 ASSERT_NOT_REACHED();
2632 // This works together with setNextKeyView to splice the WebView into
2633 // the key loop similar to the way NSScrollView does this. Note that
2634 // WebFrameView has very similar code.
2635 NSWindow *window = [self window];
2636 WebFrameView *mainFrameView = [[self mainFrame] frameView];
2638 NSResponder *previousFirstResponder = [[self window] _oldFirstResponderBeforeBecoming];
2639 BOOL fromOutside = ![previousFirstResponder isKindOfClass:[NSView class]] || (![(NSView *)previousFirstResponder isDescendantOf:self] && previousFirstResponder != self);
2641 if ([window keyViewSelectionDirection] == NSSelectingPrevious) {
2642 NSView *previousValidKeyView = [self previousValidKeyView];
2643 if ((previousValidKeyView != self) && (previousValidKeyView != mainFrameView)) {
2644 _private->becomingFirstResponder = YES;
2645 _private->becomingFirstResponderFromOutside = fromOutside;
2646 [window makeFirstResponder:previousValidKeyView];
2647 _private->becomingFirstResponderFromOutside = NO;
2648 _private->becomingFirstResponder = NO;
2655 if ([mainFrameView acceptsFirstResponder]) {
2656 _private->becomingFirstResponder = YES;
2657 _private->becomingFirstResponderFromOutside = fromOutside;
2658 [window makeFirstResponder:mainFrameView];
2659 _private->becomingFirstResponderFromOutside = NO;
2660 _private->becomingFirstResponder = NO;
2667 - (NSView *)_webcore_effectiveFirstResponder
2669 WebFrameView *frameView = [[self mainFrame] frameView];
2670 return frameView ? [frameView _webcore_effectiveFirstResponder] : [super _webcore_effectiveFirstResponder];
2673 - (void)setNextKeyView:(NSView *)aView
2675 // This works together with becomeFirstResponder to splice the WebView into
2676 // the key loop similar to the way NSScrollView does this. Note that
2677 // WebFrameView has very similar code.
2678 WebFrameView *mainFrameView = [[self mainFrame] frameView];
2679 if (mainFrameView != nil) {
2680 [mainFrameView setNextKeyView:aView];
2682 [super setNextKeyView:aView];
2686 static WebFrame *incrementFrame(WebFrame *curr, BOOL forward, BOOL wrapFlag)
2688 Frame* coreFrame = core(curr);
2690 ? coreFrame->tree()->traverseNextWithWrap(wrapFlag)
2691 : coreFrame->tree()->traversePreviousWithWrap(wrapFlag));
2694 - (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag
2696 return [self searchFor:string direction:forward caseSensitive:caseFlag wrap:wrapFlag startInSelection:NO];
2699 + (void)registerViewClass:(Class)viewClass representationClass:(Class)representationClass forMIMEType:(NSString *)MIMEType
2701 [[WebFrameView _viewTypesAllowImageTypeOmission:YES] setObject:viewClass forKey:MIMEType];
2702 [[WebDataSource _repTypesAllowImageTypeOmission:YES] setObject:representationClass forKey:MIMEType];
2704 // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
2705 // in the WebCore MIMEType registry. For now we're doing this in a safe, limited manner
2706 // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
2707 if ([viewClass class] == [WebHTMLView class])
2708 MIMETypeRegistry::getSupportedNonImageMIMETypes().add(MIMEType);
2711 - (void)setGroupName:(NSString *)groupName
2713 if (!_private->page)
2715 _private->page->setGroupName(groupName);
2718 - (NSString *)groupName
2720 if (!_private->page)
2722 return _private->page->groupName();
2725 - (double)estimatedProgress
2727 if (!_private->page)
2730 return _private->page->progress()->estimatedProgress();
2733 - (NSArray *)pasteboardTypesForSelection
2735 NSView <WebDocumentView> *documentView = [[[self _selectedOrMainFrame] frameView] documentView];
2736 if ([documentView conformsToProtocol:@protocol(WebDocumentSelection)]) {
2737 return [(NSView <WebDocumentSelection> *)documentView pasteboardTypesForSelection];
2739 return [NSArray array];
2742 - (void)writeSelectionWithPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
2744 WebFrame *frame = [self _selectedOrMainFrame];
2745 if (frame && [frame _hasSelection]) {
2746 NSView <WebDocumentView> *documentView = [[frame frameView] documentView];
2747 if ([documentView conformsToProtocol:@protocol(WebDocumentSelection)])
2748 [(NSView <WebDocumentSelection> *)documentView writeSelectionWithPasteboardTypes:types toPasteboard:pasteboard];
2752 - (NSArray *)pasteboardTypesForElement:(NSDictionary *)element
2754 if ([element objectForKey:WebElementImageURLKey] != nil) {
2755 return [NSPasteboard _web_writableTypesForImageIncludingArchive:([element objectForKey:WebElementDOMNodeKey] != nil)];
2756 } else if ([element objectForKey:WebElementLinkURLKey] != nil) {
2757 return [NSPasteboard _web_writableTypesForURL];
2758 } else if ([[element objectForKey:WebElementIsSelectedKey] boolValue]) {
2759 return [self pasteboardTypesForSelection];
2761 return [NSArray array];
2764 - (void)writeElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
2766 if ([element objectForKey:WebElementImageURLKey] != nil) {
2767 [self _writeImageForElement:element withPasteboardTypes:types toPasteboard:pasteboard];
2768 } else if ([element objectForKey:WebElementLinkURLKey] != nil) {
2769 [self _writeLinkElement:element withPasteboardTypes:types toPasteboard:pasteboard];
2770 } else if ([[element objectForKey:WebElementIsSelectedKey] boolValue]) {
2771 [self writeSelectionWithPasteboardTypes:types toPasteboard:pasteboard];
2775 - (void)moveDragCaretToPoint:(NSPoint)point
2777 if (Page* page = core(self))
2778 page->dragController()->placeDragCaret(IntPoint([self convertPoint:point toView:nil]));
2781 - (void)removeDragCaret
2783 if (Page* page = core(self))
2784 page->dragController()->dragEnded();
2787 - (void)setMainFrameURL:(NSString *)URLString
2789 [[self mainFrame] loadRequest: [NSURLRequest requestWithURL: [NSURL _web_URLWithDataAsString: URLString]]];
2792 - (NSString *)mainFrameURL
2795 ds = [[self mainFrame] provisionalDataSource];
2797 ds = [[self mainFrame] _dataSource];
2798 return [[[ds request] URL] _web_originalDataAsString];
2803 LOG (Bindings, "isLoading = %d", (int)[self _isLoading]);
2804 return [self _isLoading];
2807 - (NSString *)mainFrameTitle
2809 NSString *mainFrameTitle = [[[self mainFrame] _dataSource] pageTitle];
2810 return (mainFrameTitle != nil) ? mainFrameTitle : (NSString *)@"";
2813 - (NSImage *)mainFrameIcon
2815 return [[WebIconDatabase sharedIconDatabase] iconForURL:[[[[self mainFrame] _dataSource] _URL] _web_originalDataAsString] withSize:WebIconSmallSize];
2818 - (DOMDocument *)mainFrameDocument
2820 // only return the actual value if the state we're in gives NSTreeController
2821 // enough time to release its observers on the old model
2822 if (_private->mainFrameDocumentReady)
2823 return [[self mainFrame] DOMDocument];
2827 - (void)setDrawsBackground:(BOOL)drawsBackground
2829 if (_private->drawsBackground == drawsBackground)
2831 _private->drawsBackground = drawsBackground;
2832 [[self mainFrame] _updateBackground];
2835 - (BOOL)drawsBackground
2837 return _private->drawsBackground;
2842 @implementation WebView (WebIBActions)
2844 - (IBAction)takeStringURLFrom: sender
2846 NSString *URLString = [sender stringValue];
2848 [[self mainFrame] loadRequest: [NSURLRequest requestWithURL: [NSURL _web_URLWithDataAsString: URLString]]];
2853 if (!_private->page)
2856 return !!_private->page->backForwardList()->backItem();
2859 - (BOOL)canGoForward
2861 if (!_private->page)
2864 return !!_private->page->backForwardList()->forwardItem();
2867 - (IBAction)goBack:(id)sender
2872 - (IBAction)goForward:(id)sender
2877 - (IBAction)stopLoading:(id)sender
2879 [[self mainFrame] stopLoading];
2882 - (IBAction)reload:(id)sender
2884 [[self mainFrame] reload];
2887 // FIXME: This code should move into WebCore so that it is not duplicated in each WebKit.
2888 // (This includes canMakeTextSmaller/Larger, makeTextSmaller/Larger, and canMakeTextStandardSize/makeTextStandardSize)
2889 - (BOOL)canMakeTextSmaller
2891 return [self _canZoomOut:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
2894 - (IBAction)makeTextSmaller:(id)sender
2896 return [self _zoomOut:sender isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
2899 - (BOOL)canMakeTextLarger
2901 return [self _canZoomIn:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
2904 - (IBAction)makeTextLarger:(id)sender
2906 return [self _zoomIn:sender isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
2909 - (BOOL)canMakeTextStandardSize
2911 return [self _canResetZoom:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
2914 - (IBAction)makeTextStandardSize:(id)sender
2916 return [self _resetZoom:sender isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
2919 - (IBAction)toggleSmartInsertDelete:(id)sender
2921 [self setSmartInsertDeleteEnabled:![self smartInsertDeleteEnabled]];
2924 - (IBAction)toggleContinuousSpellChecking:(id)sender
2926 [self setContinuousSpellCheckingEnabled:![self isContinuousSpellCheckingEnabled]];
2929 - (BOOL)_responderValidateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item
2931 id responder = [self _responderForResponderOperations];
2932 if (responder != self && [responder respondsToSelector:[item action]]) {
2933 if ([responder respondsToSelector:@selector(validateUserInterfaceItemWithoutDelegate:)])
2934 return [responder validateUserInterfaceItemWithoutDelegate:item];
2935 if ([responder respondsToSelector:@selector(validateUserInterfaceItem:)])
2936 return [responder validateUserInterfaceItem:item];
2942 #define VALIDATE(name) \
2943 else if (action == @selector(name:)) { return [self _responderValidateUserInterfaceItem:item]; }
2945 - (BOOL)validateUserInterfaceItemWithoutDelegate:(id <NSValidatedUserInterfaceItem>)item
2947 SEL action = [item action];
2949 if (action == @selector(goBack:)) {
2950 return [self canGoBack];
2951 } else if (action == @selector(goForward:)) {
2952 return [self canGoForward];
2953 } else if (action == @selector(makeTextLarger:)) {
2954 return [self canMakeTextLarger];
2955 } else if (action == @selector(makeTextSmaller:)) {
2956 return [self canMakeTextSmaller];
2957 } else if (action == @selector(makeTextStandardSize:)) {
2958 return [self canMakeTextStandardSize];
2959 } else if (action == @selector(reload:)) {
2960 return [[self mainFrame] _dataSource] != nil;
2961 } else if (action == @selector(stopLoading:)) {
2962 return [self _isLoading];
2963 } else if (action == @selector(toggleContinuousSpellChecking:)) {
2964 BOOL checkMark = NO;
2966 if ([self _continuousCheckingAllowed]) {
2967 checkMark = [self isContinuousSpellCheckingEnabled];
2970 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
2971 NSMenuItem *menuItem = (NSMenuItem *)item;
2972 [menuItem setState:checkMark ? NSOnState : NSOffState];
2975 #ifndef BUILDING_ON_TIGER
2976 } else if (action == @selector(toggleGrammarChecking:)) {
2977 BOOL checkMark = [self isGrammarCheckingEnabled];
2978 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
2979 NSMenuItem *menuItem = (NSMenuItem *)item;
2980 [menuItem setState:checkMark ? NSOnState : NSOffState];
2985 FOR_EACH_RESPONDER_SELECTOR(VALIDATE)
2990 - (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item
2992 BOOL result = [self validateUserInterfaceItemWithoutDelegate:item];
2993 return CallUIDelegateReturningBoolean(result, self, @selector(webView:validateUserInterfaceItem:defaultValidation:), item, result);
2998 @implementation WebView (WebPendingPublic)
3000 - (void)scheduleInRunLoop:(NSRunLoop *)runLoop forMode:(NSString *)mode
3002 #ifndef BUILDING_ON_TIGER
3003 if (runLoop && mode)
3004 core(self)->addSchedulePair(SchedulePair::create(runLoop, (CFStringRef)mode));
3008 - (void)unscheduleFromRunLoop:(NSRunLoop *)runLoop forMode:(NSString *)mode
3010 #ifndef BUILDING_ON_TIGER
3011 if (runLoop && mode)
3012 core(self)->removeSchedulePair(SchedulePair::create(runLoop, (CFStringRef)mode));
3016 - (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag startInSelection:(BOOL)startInSelection
3018 if (_private->closed)
3021 // Get the frame holding the selection, or start with the main frame
3022 WebFrame *startFrame = [self _selectedOrMainFrame];
3024 // Search the first frame, then all the other frames, in order
3025 NSView <WebDocumentSearching> *startSearchView = nil;
3026 WebFrame *frame = startFrame;
3028 WebFrame *nextFrame = incrementFrame(frame, forward, wrapFlag);
3030 BOOL onlyOneFrame = (frame == nextFrame);
3031 ASSERT(!onlyOneFrame || frame == startFrame);
3033 id <WebDocumentView> view = [[frame frameView] documentView];
3034 if ([view conformsToProtocol:@protocol(WebDocumentSearching)]) {
3035 NSView <WebDocumentSearching> *searchView = (NSView <WebDocumentSearching> *)view;
3037 if (frame == startFrame)
3038 startSearchView = searchView;
3041 // In some cases we have to search some content twice; see comment later in this method.
3042 // We can avoid ever doing this in the common one-frame case by passing YES for wrapFlag
3043 // here, and then bailing out before we get to the code that would search again in the
3045 BOOL wrapOnThisPass = wrapFlag && onlyOneFrame;
3046 if ([searchView conformsToProtocol:@protocol(WebDocumentIncrementalSearching)])
3047 foundString = [(NSView <WebDocumentIncrementalSearching> *)searchView searchFor:string direction:forward caseSensitive:caseFlag wrap:wrapOnThisPass startInSelection:startInSelection];
3049 foundString = [searchView searchFor:string direction:forward caseSensitive:caseFlag wrap:wrapOnThisPass];
3052 if (frame != startFrame)
3053 [startFrame _clearSelection];
3054 [[self window] makeFirstResponder:searchView];
3062 } while (frame && frame != startFrame);
3064 // 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
3065 // 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
3066 // 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
3067 // some content that we already searched on the first pass. In the worst case, we could search the entire contents of this frame twice.
3068 // To fix this, we'd need to add a mechanism to specify a range in which to search.
3069 if (wrapFlag && startSearchView) {
3071 if ([startSearchView conformsToProtocol:@protocol(WebDocumentIncrementalSearching)])
3072 foundString = [(NSView <WebDocumentIncrementalSearching> *)startSearchView searchFor:string direction:forward caseSensitive:caseFlag wrap:YES startInSelection:startInSelection];
3074 foundString = [startSearchView searchFor:string direction:forward caseSensitive:caseFlag wrap:YES];
3076 [[self window] makeFirstResponder:startSearchView];
3083 - (void)setHoverFeedbackSuspended:(BOOL)newValue
3085 if (_private->hoverFeedbackSuspended == newValue)
3088 _private->hoverFeedbackSuspended = newValue;
3089 id <WebDocumentView> documentView = [[[self mainFrame] frameView] documentView];
3090 // FIXME: in a perfect world we'd do this in a general way that worked with any document view,
3091 // such as by calling a protocol method or using respondsToSelector or sending a notification.
3092 // But until there is any need for these more general solutions, we'll just hardwire it to work
3093 // with WebHTMLView.
3094 // Note that _hoverFeedbackSuspendedChanged needs to be called only on the main WebHTMLView, not
3095 // on each subframe separately.
3096 if ([documentView isKindOfClass:[WebHTMLView class]])
3097 [(WebHTMLView *)documentView _hoverFeedbackSuspendedChanged];
3100 - (BOOL)isHoverFeedbackSuspended
3102 return _private->hoverFeedbackSuspended;
3105 - (void)setMainFrameDocumentReady:(BOOL)mainFrameDocumentReady
3107 // by setting this to NO, calls to mainFrameDocument are forced to return nil
3108 // setting this to YES lets it return the actual DOMDocument value
3109 // we use this to tell NSTreeController to reset its observers and clear its state
3110 if (_private->mainFrameDocumentReady == mainFrameDocumentReady)
3112 [self _willChangeValueForKey:_WebMainFrameDocumentKey];
3113 _private->mainFrameDocumentReady = mainFrameDocumentReady;
3114 [self _didChangeValueForKey:_WebMainFrameDocumentKey];
3115 // this will cause observers to call mainFrameDocument where this flag will be checked
3118 // This method name is used by Mail on Tiger (but not post-Tiger), so we shouldn't delete it
3119 // until the day comes when we're no longer supporting Mail on Tiger.
3120 - (WebFrame *)_frameForCurrentSelection
3122 return [self _selectedOrMainFrame];
3125 - (void)setTabKeyCyclesThroughElements:(BOOL)cyclesElements
3127 _private->tabKeyCyclesThroughElementsChanged = YES;
3129 _private->page->setTabKeyCyclesThroughElements(cyclesElements);
3132 - (BOOL)tabKeyCyclesThroughElements
3134 return _private->page && _private->page->tabKeyCyclesThroughElements();
3137 - (void)setScriptDebugDelegate:(id)delegate
3139 _private->scriptDebugDelegate = delegate;
3140 [_private->scriptDebugDelegateForwarder release];
3141 _private->scriptDebugDelegateForwarder = nil;
3143 [self _attachScriptDebuggerToAllFrames];
3145 [self _detachScriptDebuggerFromAllFrames];
3148 - (id)scriptDebugDelegate
3150 return _private->scriptDebugDelegate;
3155 Frame* coreFrame = core([self mainFrame]);
3158 return coreFrame->shouldClose();
3161 static NSAppleEventDescriptor* aeDescFromJSValue(ExecState* exec, JSValue* jsValue)
3163 NSAppleEventDescriptor* aeDesc = 0;
3164 switch (jsValue->type()) {
3166 aeDesc = [NSAppleEventDescriptor descriptorWithBoolean:jsValue->getBoolean()];
3169 aeDesc = [NSAppleEventDescriptor descriptorWithString:String(jsValue->getString())];
3172 double value = jsValue->getNumber();
3173 int intValue = (int)value;
3174 if (value == intValue)
3175 aeDesc = [NSAppleEventDescriptor descriptorWithDescriptorType:typeSInt32 bytes:&intValue length:sizeof(intValue)];
3177 aeDesc = [NSAppleEventDescriptor descriptorWithDescriptorType:typeIEEE64BitFloatingPoint bytes:&value length:sizeof(value)];
3181 JSObject* object = jsValue->getObject();
3182 if (object->inherits(&DateInstance::info)) {
3183 DateInstance* date = static_cast<DateInstance*>(object);
3186 if (date->getTime(ms, tzOffset)) {
3187 CFAbsoluteTime utcSeconds = ms / 1000 - kCFAbsoluteTimeIntervalSince1970;
3189 if (noErr == UCConvertCFAbsoluteTimeToLongDateTime(utcSeconds, &ldt))
3190 aeDesc = [NSAppleEventDescriptor descriptorWithDescriptorType:typeLongDateTime bytes:&ldt length:sizeof(ldt)];
3193 else if (object->inherits(&ArrayInstance::info)) {
3194 static HashSet<JSObject*> visitedElems;
3195 if (!visitedElems.contains(object)) {
3196 visitedElems.add(object);
3198 ArrayInstance* array = static_cast<ArrayInstance*>(object);
3199 aeDesc = [NSAppleEventDescriptor listDescriptor];
3200 unsigned numItems = array->getLength();
3201 for (unsigned i = 0; i < numItems; ++i)
3202 [aeDesc insertDescriptor:aeDescFromJSValue(exec, array->getItem(i)) atIndex:0];
3204 visitedElems.remove(object);
3208 JSValue* primitive = object->toPrimitive(exec);
3209 if (exec->hadException()) {
3210 exec->clearException();
3211 return [NSAppleEventDescriptor nullDescriptor];
3213 return aeDescFromJSValue(exec, primitive);
3218 aeDesc = [NSAppleEventDescriptor descriptorWithTypeCode:cMissingValue];
3221 LOG_ERROR("Unknown JavaScript type: %d", jsValue->type());
3223 case UnspecifiedType:
3225 case GetterSetterType:
3226 aeDesc = [NSAppleEventDescriptor nullDescriptor];
3233 - (NSAppleEventDescriptor *)aeDescByEvaluatingJavaScriptFromString:(NSString *)script
3235 Frame* coreFrame = core([self mainFrame]);
3238 if (!coreFrame->document())
3240 JSValue* result = coreFrame->loader()->executeScript(script, true);
3241 if (!result) // FIXME: pass errors
3244 return aeDescFromJSValue(coreFrame->scriptProxy()->globalObject()->globalExec(), result);
3247 - (BOOL)canMarkAllTextMatches
3249 WebFrame *frame = [self mainFrame];
3251 id <WebDocumentView> view = [[frame frameView] documentView];
3252 if (view && ![view conformsToProtocol:@protocol(WebMultipleTextMatches)])
3255 frame = incrementFrame(frame, YES, NO);
3261 - (NSUInteger)markAllMatchesForText:(NSString *)string caseSensitive:(BOOL)caseFlag highlight:(BOOL)highlight limit:(NSUInteger)limit
3263 WebFrame *frame = [self mainFrame];
3264 unsigned matchCount = 0;
3266 id <WebDocumentView> view = [[frame frameView] documentView];
3267 if ([view conformsToProtocol:@protocol(WebMultipleTextMatches)]) {
3268 [(NSView <WebMultipleTextMatches>*)view setMarkedTextMatchesAreHighlighted:highlight];
3270 ASSERT(limit == 0 || matchCount < limit);
3271 matchCount += [(NSView <WebMultipleTextMatches>*)view markAllMatchesForText:string caseSensitive:caseFlag limit:limit == 0 ? 0 : limit - matchCount];
3273 // Stop looking if we've reached the limit. A limit of 0 means no limit.
3274 if (limit > 0 && matchCount >= limit)
3278 frame = incrementFrame(frame, YES, NO);
3284 - (void)unmarkAllTextMatches
3286 WebFrame *frame = [self mainFrame];
3288 id <WebDocumentView> view = [[frame frameView] documentView];
3289 if ([view conformsToProtocol:@protocol(WebMultipleTextMatches)])
3290 [(NSView <WebMultipleTextMatches>*)view unmarkAllTextMatches];
3292 frame = incrementFrame(frame, YES, NO);
3296 - (NSArray *)rectsForTextMatches
3298 NSMutableArray *result = [NSMutableArray array];
3299 WebFrame *frame = [self mainFrame];
3301 id <WebDocumentView> view = [[frame frameView] documentView];
3302 if ([view conformsToProtocol:@protocol(WebMultipleTextMatches)]) {
3303 NSView <WebMultipleTextMatches> *documentView = (NSView <WebMultipleTextMatches> *)view;
3304 NSRect documentViewVisibleRect = [documentView visibleRect];
3305 NSArray *originalRects = [documentView rectsForTextMatches];
3306 unsigned rectCount = [originalRects count];
3308 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
3309 for (rectIndex = 0; rectIndex < rectCount; ++rectIndex) {
3310 NSRect r = [[originalRects objectAtIndex:rectIndex] rectValue];
3311 // Clip rect to document view's visible rect so rect is confined to subframe
3312 r = NSIntersectionRect(r, documentViewVisibleRect);
3313 if (NSIsEmptyRect(r))
3316 // Convert rect to our coordinate system
3317 r = [documentView convertRect:r toView:self];
3318 [result addObject:[NSValue valueWithRect:r]];
3319 if (rectIndex % 10 == 0) {
3321 pool = [[NSAutoreleasePool alloc] init];
3327 frame = incrementFrame(frame, YES, NO);
3333 - (void)scrollDOMRangeToVisible:(DOMRange *)range
3335 [[[[range startContainer] ownerDocument] webFrame] _scrollDOMRangeToVisible:range];
3340 return _private->allowsUndo;
3343 - (void)setAllowsUndo:(BOOL)flag
3345 _private->allowsUndo = flag;
3348 - (void)setPageSizeMultiplier:(float)m
3350 [self _setZoomMultiplier:m isTextOnly:NO];
3353 - (float)pageSizeMultiplier
3355 return !_private->zoomMultiplierIsTextOnly ? _private->zoomMultiplier : 1.0f;
3358 - (BOOL)canZoomPageIn
3360 return [self _canZoomIn:NO];
3363 - (IBAction)zoomPageIn:(id)sender
3365 return [self _zoomIn:sender isTextOnly:NO];
3368 - (BOOL)canZoomPageOut
3370 return [self _canZoomOut:NO];
3373 - (IBAction)zoomPageOut:(id)sender
3375 return [self _zoomOut:sender isTextOnly:NO];
3378 - (BOOL)canResetPageZoom
3380 return [self _canResetZoom:NO];
3383 - (IBAction)resetPageZoom:(id)sender
3385 return [self _resetZoom:sender isTextOnly:NO];
3390 @implementation WebView (WebViewPrintingPrivate)
3392 - (float)_headerHeight
3394 return CallUIDelegateReturningFloat(self, @selector(webViewHeaderHeight:));
3397 - (float)_footerHeight
3399 return CallUIDelegateReturningFloat(self, @selector(webViewFooterHeight:));
3402 - (void)_drawHeaderInRect:(NSRect)rect
3404 #ifdef DEBUG_HEADER_AND_FOOTER
3405 NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
3406 [currentContext saveGraphicsState];
3407 [[NSColor yellowColor] set];
3409 [currentContext restoreGraphicsState];
3412 SEL selector = @selector(webView:drawHeaderInRect:);
3413 if (![_private->UIDelegate respondsToSelector:selector])
3416 NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
3417 [currentContext saveGraphicsState];
3420 CallUIDelegate(self, selector, rect);
3422 [currentContext restoreGraphicsState];
3425 - (void)_drawFooterInRect:(NSRect)rect
3427 #ifdef DEBUG_HEADER_AND_FOOTER
3428 NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
3429 [currentContext saveGraphicsState];
3430 [[NSColor cyanColor] set];
3432 [currentContext restoreGraphicsState];
3435 SEL selector = @selector(webView:drawFooterInRect:);
3436 if (![_private->UIDelegate respondsToSelector:selector])
3439 NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
3440 [currentContext saveGraphicsState];
3443 CallUIDelegate(self, selector, rect);
3445 [currentContext restoreGraphicsState];
3448 - (void)_adjustPrintingMarginsForHeaderAndFooter
3450 NSPrintOperation *op = [NSPrintOperation currentOperation];
3451 NSPrintInfo *info = [op printInfo];
3452 NSMutableDictionary *infoDictionary = [info dictionary];
3454 // We need to modify the top and bottom margins in the NSPrintInfo to account for the space needed by the
3455 // header and footer. Because this method can be called more than once on the same NSPrintInfo (see 5038087),
3456 // we stash away the unmodified top and bottom margins the first time this method is called, and we read from
3457 // those stashed-away values on subsequent calls.
3458 float originalTopMargin;
3459 float originalBottomMargin;
3460 NSNumber *originalTopMarginNumber = [infoDictionary objectForKey:WebKitOriginalTopPrintingMarginKey];
3461 if (!originalTopMarginNumber) {
3462 ASSERT(![infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey]);
3463 originalTopMargin = [info topMargin];
3464 originalBottomMargin = [info bottomMargin];
3465 [infoDictionary setObject:[NSNumber numberWithFloat:originalTopMargin] forKey:WebKitOriginalTopPrintingMarginKey];
3466 [infoDictionary setObject:[NSNumber numberWithFloat:originalBottomMargin] forKey:WebKitOriginalBottomPrintingMarginKey];
3468 ASSERT([originalTopMarginNumber isKindOfClass:[NSNumber class]]);
3469 ASSERT([[infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey] isKindOfClass:[NSNumber class]]);
3470 originalTopMargin = [originalTopMarginNumber floatValue];
3471 originalBottomMargin = [[infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey] floatValue];
3474 float scale = [op _web_pageSetupScaleFactor];
3475 [info setTopMargin:originalTopMargin + [self _headerHeight] * scale];
3476 [info setBottomMargin:originalBottomMargin + [self _footerHeight] * scale];
3479 - (void)_drawHeaderAndFooter
3481 // The header and footer rect height scales with the page, but the width is always
3482 // all the way across the printed page (inset by printing margins).
3483 NSPrintOperation *op = [NSPrintOperation currentOperation];
3484 float scale = [op _web_pageSetupScaleFactor];
3485 NSPrintInfo *printInfo = [op printInfo];
3486 NSSize paperSize = [printInfo paperSize];
3487 float headerFooterLeft = [printInfo leftMargin]/scale;
3488 float headerFooterWidth = (paperSize.width - ([printInfo leftMargin] + [printInfo rightMargin]))/scale;
3489 NSRect footerRect = NSMakeRect(headerFooterLeft, [printInfo bottomMargin]/scale - [self _footerHeight] ,
3490 headerFooterWidth, [self _footerHeight]);
3491 NSRect headerRect = NSMakeRect(headerFooterLeft, (paperSize.height - [printInfo topMargin])/scale,
3492 headerFooterWidth, [self _headerHeight]);
3494 [self _drawHeaderInRect:headerRect];
3495 [self _drawFooterInRect:footerRect];
3499 @implementation WebView (WebDebugBinding)
3501 - (void)addObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context
3503 LOG (Bindings, "addObserver:%p forKeyPath:%@ options:%x context:%p", anObserver, keyPath, options, context);
3504 [super addObserver:anObserver forKeyPath:keyPath options:options context:context];
3507 - (void)removeObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath
3509 LOG (Bindings, "removeObserver:%p forKeyPath:%@", anObserver, keyPath);
3510 [super removeObserver:anObserver forKeyPath:keyPath];
3515 //==========================================================================================
3518 @implementation WebView (WebViewCSS)
3520 - (DOMCSSStyleDeclaration *)computedStyleForElement:(DOMElement *)element pseudoElement:(NSString *)pseudoElement
3522 // FIXME: is this the best level for this conversion?
3523 if (pseudoElement == nil)
3524 pseudoElement = @"";
3526 return [[element ownerDocument] getComputedStyle:element pseudoElement:pseudoElement];
3531 @implementation WebView (WebViewEditing)
3533 - (DOMRange *)editableDOMRangeForPoint:(NSPoint)point
3535 Page* page = core(self);
3538 return kit(page->mainFrame()->editor()->rangeForPoint(IntPoint([self convertPoint:point toView:nil])).get());
3541 - (BOOL)_shouldChangeSelectedDOMRange:(DOMRange *)currentRange toDOMRange:(DOMRange *)proposedRange affinity:(NSSelectionAffinity)selectionAffinity stillSelecting:(BOOL)flag;
3543 // 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
3544 if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_APERTURE_QUIRK) && [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.Aperture"])
3546 return [[self _editingDelegateForwarder] webView:self shouldChangeSelectedDOMRange:currentRange toDOMRange:proposedRange affinity:selectionAffinity stillSelecting:flag];
3549 - (BOOL)maintainsInactiveSelection
3554 - (void)setSelectedDOMRange:(DOMRange *)range affinity:(NSSelectionAffinity)selectionAffinity
3556 Frame* coreFrame = core([self _selectedOrMainFrame]);
3561 coreFrame->selectionController()->clear();
3563 // Derive the frame to use from the range passed in.
3564 // Using _selectedOrMainFrame could give us a different document than
3565 // the one the range uses.
3566 coreFrame = core([range startContainer])->document()->frame();
3570 coreFrame->selectionController()->setSelectedRange([range _range], core(selectionAffinity), true);
3574 - (DOMRange *)selectedDOMRange
3576 Frame* coreFrame = core([self _selectedOrMainFrame]);
3579 return kit(coreFrame->selectionController()->toRange().get());
3582 - (NSSelectionAffinity)selectionAffinity
3584 Frame* coreFrame = core([self _selectedOrMainFrame]);
3586 return NSSelectionAffinityDownstream;
3587 return kit(coreFrame->selectionController()->affinity());
3590 - (void)setEditable:(BOOL)flag
3592 if (_private->editable != flag) {
3593 _private->editable = flag;
3594 if (!_private->tabKeyCyclesThroughElementsChanged && _private->page)
3595 _private->page->setTabKeyCyclesThroughElements(!flag);
3596 Frame* mainFrame = core([self mainFrame]);
3599 mainFrame->applyEditingStyleToBodyElement();
3600 // If the WebView is made editable and the selection is empty, set it to something.
3601 if (![self selectedDOMRange])
3602 mainFrame->setSelectionFromNone();
3604 mainFrame->removeEditingStyleFromBodyElement();
3611 return _private->editable;
3614 - (void)setTypingStyle:(DOMCSSStyleDeclaration *)style
3616 // We don't know enough at thls level to pass in a relevant WebUndoAction; we'd have to
3617 // change the API to allow this.
3618 [[self _selectedOrMainFrame] _setTypingStyle:style withUndoAction:EditActionUnspecified];
3621 - (DOMCSSStyleDeclaration *)typingStyle
3623 return [[self _selectedOrMainFrame] _typingStyle];
3626 - (void)setSmartInsertDeleteEnabled:(BOOL)flag
3628 _private->smartInsertDeleteEnabled = flag;
3631 - (BOOL)smartInsertDeleteEnabled
3633 return _private->smartInsertDeleteEnabled;
3636 - (void)setContinuousSpellCheckingEnabled:(BOOL)flag
3638 if (continuousSpellCheckingEnabled != flag) {
3639 continuousSpellCheckingEnabled = flag;
3640 [[NSUserDefaults standardUserDefaults] setBool:continuousSpellCheckingEnabled forKey:WebContinuousSpellCheckingEnabled];
3643 if ([self isContinuousSpellCheckingEnabled]) {
3644 [[self class] _preflightSpellChecker];
3646 [[self mainFrame] _unmarkAllMisspellings];
3650 - (BOOL)isContinuousSpellCheckingEnabled
3652 return (continuousSpellCheckingEnabled && [self _continuousCheckingAllowed]);
3655 - (NSInteger)spellCheckerDocumentTag
3657 if (!_private->hasSpellCheckerDocumentTag) {
3658 _private->spellCheckerDocumentTag = [NSSpellChecker uniqueSpellDocumentTag];
3659 _private->hasSpellCheckerDocumentTag = YES;
3661 return _private->spellCheckerDocumentTag;
3664 - (NSUndoManager *)undoManager
3666 if (!_private->allowsUndo)
3669 NSUndoManager *undoManager = [[self _editingDelegateForwarder] undoManagerForWebView:self];
3673 return [super undoManager];
3676 - (void)registerForEditingDelegateNotification:(NSString *)name selector:(SEL)selector
3678 NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
3679 if ([_private->editingDelegate respondsToSelector:selector])
3680 [defaultCenter addObserver:_private->editingDelegate selector:selector name:name object:self];
3683 - (void)setEditingDelegate:(id)delegate
3685 if (_private->editingDelegate ==&nbs