2 * Copyright (C) 2005, 2006, 2007, 2008, 2009 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"
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 "WebDefaultUIDelegate.h"
43 #import "WebDocument.h"
44 #import "WebDocumentInternal.h"
45 #import "WebDownload.h"
46 #import "WebDownloadInternal.h"
47 #import "WebDragClient.h"
48 #import "WebDynamicScrollBarsViewInternal.h"
49 #import "WebEditingDelegate.h"
50 #import "WebEditorClient.h"
51 #import "WebFormDelegatePrivate.h"
52 #import "WebFrameInternal.h"
53 #import "WebFrameViewInternal.h"
54 #import "WebHTMLRepresentation.h"
55 #import "WebHTMLViewInternal.h"
56 #import "WebHistoryItemInternal.h"
57 #import "WebIconDatabaseInternal.h"
58 #import "WebInspector.h"
59 #import "WebInspectorClient.h"
60 #import "WebKitErrors.h"
61 #import "WebKitLogging.h"
62 #import "WebKitNSStringExtras.h"
63 #import "WebKitStatisticsPrivate.h"
64 #import "WebKitSystemBits.h"
65 #import "WebKitVersionChecks.h"
66 #import "WebLocalizableStrings.h"
67 #import "WebNodeHighlight.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 "WebScriptDebugDelegate.h"
87 #import "WebTextIterator.h"
88 #import "WebUIDelegate.h"
89 #import "WebUIDelegatePrivate.h"
90 #import <CoreFoundation/CFSet.h>
91 #import <Foundation/NSURLConnection.h>
92 #import <WebCore/ApplicationCacheStorage.h>
93 #import <WebCore/Cache.h>
94 #import <WebCore/ColorMac.h>
95 #import <WebCore/Cursor.h>
96 #import <WebCore/Document.h>
97 #import <WebCore/DocumentLoader.h>
98 #import <WebCore/DragController.h>
99 #import <WebCore/DragData.h>
100 #import <WebCore/Editor.h>
101 #import <WebCore/EventHandler.h>
102 #import <WebCore/ExceptionHandlers.h>
103 #import <WebCore/FocusController.h>
104 #import <WebCore/Frame.h>
105 #import <WebCore/FrameLoader.h>
106 #import <WebCore/FrameView.h>
107 #import <WebCore/FrameTree.h>
108 #import <WebCore/GCController.h>
109 #import <WebCore/HTMLNames.h>
110 #import <WebCore/HistoryItem.h>
111 #import <WebCore/IconDatabase.h>
112 #import <WebCore/Logging.h>
113 #import <WebCore/MIMETypeRegistry.h>
114 #import <WebCore/Page.h>
115 #import <WebCore/PageCache.h>
116 #import <WebCore/PageGroup.h>
117 #import <WebCore/PlatformMouseEvent.h>
118 #import <WebCore/ProgressTracker.h>
119 #import <WebCore/ScriptController.h>
120 #import <WebCore/ScriptValue.h>
121 #import <WebCore/SelectionController.h>
122 #import <WebCore/Settings.h>
123 #import <WebCore/TextResourceDecoder.h>
124 #import <WebCore/ThreadCheck.h>
125 #import <WebCore/WebCoreObjCExtras.h>
126 #import <WebCore/WebCoreTextRenderer.h>
127 #import <WebCore/WebCoreView.h>
128 #import <WebKit/DOM.h>
129 #import <WebKit/DOMExtensions.h>
130 #import <WebKit/DOMPrivate.h>
131 #import <WebKitSystemInterface.h>
132 #import <mach-o/dyld.h>
133 #import <objc/objc-auto.h>
134 #import <objc/objc-runtime.h>
135 #import <runtime/ArrayPrototype.h>
136 #import <runtime/DateInstance.h>
137 #import <runtime/InitializeThreading.h>
138 #import <runtime/JSLock.h>
139 #import <runtime/JSValue.h>
140 #import <wtf/Assertions.h>
141 #import <wtf/HashTraits.h>
142 #import <wtf/RefCountedLeakCounter.h>
143 #import <wtf/RefPtr.h>
144 #import <wtf/StdLibExtras.h>
146 #if ENABLE(DASHBOARD_SUPPORT)
147 #import <WebKit/WebDashboardRegion.h>
150 using namespace WebCore;
153 #if defined(__ppc__) || defined(__ppc64__)
154 #define PROCESSOR "PPC"
155 #elif defined(__i386__) || defined(__x86_64__)
156 #define PROCESSOR "Intel"
158 #error Unknown architecture
161 #define FOR_EACH_RESPONDER_SELECTOR(macro) \
163 macro(alignJustified) \
166 macro(capitalizeWord) \
167 macro(centerSelectionInVisibleArea) \
168 macro(changeAttributes) \
169 macro(changeBaseWritingDirection) \
170 macro(changeBaseWritingDirectionToLTR) \
171 macro(changeBaseWritingDirectionToRTL) \
173 macro(changeDocumentBackgroundColor) \
175 macro(changeSpelling) \
176 macro(checkSpelling) \
182 macro(deleteBackward) \
183 macro(deleteBackwardByDecomposingPreviousCharacter) \
184 macro(deleteForward) \
185 macro(deleteToBeginningOfLine) \
186 macro(deleteToBeginningOfParagraph) \
187 macro(deleteToEndOfLine) \
188 macro(deleteToEndOfParagraph) \
189 macro(deleteToMark) \
190 macro(deleteWordBackward) \
191 macro(deleteWordForward) \
192 macro(ignoreSpelling) \
194 macro(insertBacktab) \
195 macro(insertLineBreak) \
196 macro(insertNewline) \
197 macro(insertNewlineIgnoringFieldEditor) \
198 macro(insertParagraphSeparator) \
200 macro(insertTabIgnoringFieldEditor) \
201 macro(lowercaseWord) \
202 macro(makeBaseWritingDirectionLeftToRight) \
203 macro(makeBaseWritingDirectionRightToLeft) \
204 macro(makeTextWritingDirectionLeftToRight) \
205 macro(makeTextWritingDirectionNatural) \
206 macro(makeTextWritingDirectionRightToLeft) \
207 macro(moveBackward) \
208 macro(moveBackwardAndModifySelection) \
210 macro(moveDownAndModifySelection) \
212 macro(moveForwardAndModifySelection) \
214 macro(moveLeftAndModifySelection) \
215 macro(moveParagraphBackwardAndModifySelection) \
216 macro(moveParagraphForwardAndModifySelection) \
218 macro(moveRightAndModifySelection) \
219 macro(moveToBeginningOfDocument) \
220 macro(moveToBeginningOfDocumentAndModifySelection) \
221 macro(moveToBeginningOfLine) \
222 macro(moveToBeginningOfLineAndModifySelection) \
223 macro(moveToBeginningOfParagraph) \
224 macro(moveToBeginningOfParagraphAndModifySelection) \
225 macro(moveToBeginningOfSentence) \
226 macro(moveToBeginningOfSentenceAndModifySelection) \
227 macro(moveToEndOfDocument) \
228 macro(moveToEndOfDocumentAndModifySelection) \
229 macro(moveToEndOfLine) \
230 macro(moveToEndOfLineAndModifySelection) \
231 macro(moveToEndOfParagraph) \
232 macro(moveToEndOfParagraphAndModifySelection) \
233 macro(moveToEndOfSentence) \
234 macro(moveToEndOfSentenceAndModifySelection) \
236 macro(moveUpAndModifySelection) \
237 macro(moveWordBackward) \
238 macro(moveWordBackwardAndModifySelection) \
239 macro(moveWordForward) \
240 macro(moveWordForwardAndModifySelection) \
241 macro(moveWordLeft) \
242 macro(moveWordLeftAndModifySelection) \
243 macro(moveWordRight) \
244 macro(moveWordRightAndModifySelection) \
247 macro(pageDownAndModifySelection) \
249 macro(pageUpAndModifySelection) \
251 macro(pasteAsPlainText) \
252 macro(pasteAsRichText) \
254 macro(performFindPanelAction) \
255 macro(scrollLineDown) \
256 macro(scrollLineUp) \
257 macro(scrollPageDown) \
258 macro(scrollPageUp) \
259 macro(scrollToBeginningOfDocument) \
260 macro(scrollToEndOfDocument) \
263 macro(selectParagraph) \
264 macro(selectSentence) \
265 macro(selectToMark) \
268 macro(showGuessPanel) \
269 macro(startSpeaking) \
270 macro(stopSpeaking) \
273 macro(swapWithMark) \
274 macro(takeFindStringFromSelection) \
275 macro(toggleBaseWritingDirection) \
279 macro(uppercaseWord) \
281 macro(yankAndSelect) \
283 #define WebKitOriginalTopPrintingMarginKey @"WebKitOriginalTopMargin"
284 #define WebKitOriginalBottomPrintingMarginKey @"WebKitOriginalBottomMargin"
286 #define KeyboardUIModeDidChangeNotification @"com.apple.KeyboardUIModeDidChange"
287 #define AppleKeyboardUIMode CFSTR("AppleKeyboardUIMode")
288 #define UniversalAccessDomain CFSTR("com.apple.universalaccess")
290 #if USE(ACCELERATED_COMPOSITING)
291 #define UsingAcceleratedCompositingProperty @"_isUsingAcceleratedCompositing"
295 static BOOL s_didSetCacheModel;
296 static WebCacheModel s_cacheModel = WebCacheModelDocumentViewer;
298 static BOOL applicationIsTerminating;
299 static int pluginDatabaseClientCount = 0;
302 static const char webViewIsOpen[] = "At least one WebView is still open.";
305 @interface NSSpellChecker (AppKitSecretsIKnow)
306 - (void)_preflightChosenSpellServer;
309 @interface NSView (AppKitSecretsIKnow)
310 - (NSView *)_hitTest:(NSPoint *)aPoint dragTypes:(NSSet *)types;
311 - (void)_autoscrollForDraggingInfo:(id)dragInfo timeDelta:(NSTimeInterval)repeatDelta;
312 - (BOOL)_shouldAutoscrollForDraggingInfo:(id)dragInfo;
315 @interface NSWindow (AppKitSecretsIKnow)
316 - (id)_oldFirstResponderBeforeBecoming;
319 @interface NSObject (ValidateWithoutDelegate)
320 - (BOOL)validateUserInterfaceItemWithoutDelegate:(id <NSValidatedUserInterfaceItem>)item;
323 @interface _WebSafeForwarder : NSObject
325 id target; // Non-retained. Don't retain delegates.
327 BOOL catchExceptions;
329 - (id)initWithTarget:(id)target defaultTarget:(id)defaultTarget catchExceptions:(BOOL)catchExceptions;
332 @interface WebViewPrivate : NSObject {
337 id UIDelegateForwarder;
338 id resourceProgressDelegate;
341 id policyDelegateForwarder;
342 id frameLoadDelegate;
343 id frameLoadDelegateForwarder;
344 id <WebFormDelegate> formDelegate;
346 id editingDelegateForwarder;
347 id scriptDebugDelegate;
349 WebInspector *inspector;
350 WebNodeHighlight *currentNodeHighlight;
354 float zoomMultiplier;
356 NSString *applicationNameForUserAgent;
358 BOOL userAgentOverridden;
360 WebPreferences *preferences;
361 BOOL useSiteSpecificSpoofing;
363 NSWindow *hostWindow;
365 int programmaticFocusCount;
367 WebResourceDelegateImplementationCache resourceLoadDelegateImplementations;
368 WebFrameLoadDelegateImplementationCache frameLoadDelegateImplementations;
369 WebScriptDebugDelegateImplementationCache scriptDebugDelegateImplementations;
371 void *observationInfo;
374 BOOL shouldCloseWithWindow;
375 BOOL mainFrameDocumentReady;
376 BOOL drawsBackground;
378 BOOL tabKeyCyclesThroughElementsChanged;
379 BOOL becomingFirstResponder;
380 BOOL becomingFirstResponderFromOutside;
381 BOOL hoverFeedbackSuspended;
383 BOOL catchesDelegateExceptions;
385 NSColor *backgroundColor;
387 NSString *mediaStyle;
389 BOOL hasSpellCheckerDocumentTag;
390 NSInteger spellCheckerDocumentTag;
392 BOOL smartInsertDeleteEnabled;
393 BOOL selectTrailingWhitespaceEnabled;
395 #if ENABLE(DASHBOARD_SUPPORT)
396 BOOL dashboardBehaviorAlwaysSendMouseEventsToAllWindows;
397 BOOL dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns;
398 BOOL dashboardBehaviorAlwaysAcceptsFirstMouse;
399 BOOL dashboardBehaviorAllowWheelScrolling;
402 // WebKit has both a global plug-in database and a separate, per WebView plug-in database. Dashboard uses the per WebView database.
403 WebPluginDatabase *pluginDatabase;
405 HashMap<unsigned long, RetainPtr<id> > identifierMap;
407 BOOL _keyboardUIModeAccessed;
408 KeyboardUIMode _keyboardUIMode;
410 BOOL shouldUpdateWhileOffscreen;
412 // When this flag is set, we will not make any subviews underneath this WebView. This means no WebFrameViews and no WebHTMLViews.
413 BOOL useDocumentViews;
415 #if USE(ACCELERATED_COMPOSITING)
416 // When this flag is set, next time a WebHTMLView draws, it needs to temporarily disable screen updates
417 // so that the NSView drawing is visually synchronized with CALayer updates.
418 BOOL needsOneShotDrawingSynchronization;
419 // Number of WebHTMLViews using accelerated compositing. Used to implement _isUsingAcceleratedCompositing.
420 int acceleratedFramesCount;
425 @interface WebView (WebFileInternal)
426 - (WebFrame *)_selectedOrMainFrame;
428 - (WebFrameView *)_frameViewAtWindowPoint:(NSPoint)point;
429 - (WebFrame *)_focusedFrame;
430 + (void)_preflightSpellChecker;
431 - (BOOL)_continuousCheckingAllowed;
432 - (NSResponder *)_responderForResponderOperations;
435 @interface WebView (WebCallDelegateFunctions)
438 static void patchMailRemoveAttributesMethod();
440 NSString *WebElementDOMNodeKey = @"WebElementDOMNode";
441 NSString *WebElementFrameKey = @"WebElementFrame";
442 NSString *WebElementImageKey = @"WebElementImage";
443 NSString *WebElementImageAltStringKey = @"WebElementImageAltString";
444 NSString *WebElementImageRectKey = @"WebElementImageRect";
445 NSString *WebElementImageURLKey = @"WebElementImageURL";
446 NSString *WebElementIsSelectedKey = @"WebElementIsSelected";
447 NSString *WebElementLinkLabelKey = @"WebElementLinkLabel";
448 NSString *WebElementLinkTargetFrameKey = @"WebElementTargetFrame";
449 NSString *WebElementLinkTitleKey = @"WebElementLinkTitle";
450 NSString *WebElementLinkURLKey = @"WebElementLinkURL";
451 NSString *WebElementSpellingToolTipKey = @"WebElementSpellingToolTip";
452 NSString *WebElementTitleKey = @"WebElementTitle";
453 NSString *WebElementLinkIsLiveKey = @"WebElementLinkIsLive";
454 NSString *WebElementIsContentEditableKey = @"WebElementIsContentEditableKey";
456 NSString *WebViewProgressStartedNotification = @"WebProgressStartedNotification";
457 NSString *WebViewProgressEstimateChangedNotification = @"WebProgressEstimateChangedNotification";
458 NSString *WebViewProgressFinishedNotification = @"WebProgressFinishedNotification";
460 NSString * const WebViewDidBeginEditingNotification = @"WebViewDidBeginEditingNotification";
461 NSString * const WebViewDidChangeNotification = @"WebViewDidChangeNotification";
462 NSString * const WebViewDidEndEditingNotification = @"WebViewDidEndEditingNotification";
463 NSString * const WebViewDidChangeTypingStyleNotification = @"WebViewDidChangeTypingStyleNotification";
464 NSString * const WebViewDidChangeSelectionNotification = @"WebViewDidChangeSelectionNotification";
466 enum { WebViewVersion = 4 };
468 #define timedLayoutSize 4096
470 static NSMutableSet *schemesWithRepresentationsSet;
472 NSString *_WebCanGoBackKey = @"canGoBack";
473 NSString *_WebCanGoForwardKey = @"canGoForward";
474 NSString *_WebEstimatedProgressKey = @"estimatedProgress";
475 NSString *_WebIsLoadingKey = @"isLoading";
476 NSString *_WebMainFrameIconKey = @"mainFrameIcon";
477 NSString *_WebMainFrameTitleKey = @"mainFrameTitle";
478 NSString *_WebMainFrameURLKey = @"mainFrameURL";
479 NSString *_WebMainFrameDocumentKey = @"mainFrameDocument";
481 @interface WebProgressItem : NSObject
484 long long bytesReceived;
485 long long estimatedLength;
489 @implementation WebProgressItem
492 static BOOL continuousSpellCheckingEnabled;
493 #ifndef BUILDING_ON_TIGER
494 static BOOL grammarCheckingEnabled;
497 @implementation WebViewPrivate
501 JSC::initializeThreading();
502 #ifndef BUILDING_ON_TIGER
503 WebCoreObjCFinalizeOnMainThread(self);
512 JSC::initializeThreading();
515 #if ENABLE(DASHBOARD_SUPPORT)
516 dashboardBehaviorAllowWheelScrolling = YES;
518 shouldCloseWithWindow = objc_collecting_enabled();
519 continuousSpellCheckingEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebContinuousSpellCheckingEnabled];
521 #ifndef BUILDING_ON_TIGER
522 grammarCheckingEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebGrammarCheckingEnabled];
527 pluginDatabaseClientCount++;
529 shouldUpdateWhileOffscreen = YES;
536 ASSERT(applicationIsTerminating || !page);
537 ASSERT(applicationIsTerminating || !preferences);
539 [applicationNameForUserAgent release];
540 [backgroundColor release];
543 [currentNodeHighlight release];
545 [hostWindow release];
547 [policyDelegateForwarder release];
548 [UIDelegateForwarder release];
549 [frameLoadDelegateForwarder release];
550 [editingDelegateForwarder release];
552 [mediaStyle release];
559 ASSERT_MAIN_THREAD();
566 @implementation WebView (AllWebViews)
568 static CFSetCallBacks NonRetainingSetCallbacks = {
577 static CFMutableSetRef allWebViewsSet;
579 + (void)_makeAllWebViewsPerformSelector:(SEL)selector
584 [(NSMutableSet *)allWebViewsSet makeObjectsPerformSelector:selector];
587 - (void)_removeFromAllWebViewsSet
590 CFSetRemoveValue(allWebViewsSet, self);
593 - (void)_addToAllWebViewsSet
596 allWebViewsSet = CFSetCreateMutable(NULL, 0, &NonRetainingSetCallbacks);
598 CFSetSetValue(allWebViewsSet, self);
603 @implementation WebView (WebPrivate)
605 static inline int callGestalt(OSType selector)
608 Gestalt(selector, &value);
612 // Uses underscores instead of dots because if "4." ever appears in a user agent string, old DHTML libraries treat it as Netscape 4.
613 static NSString *createMacOSXVersionString()
615 // Can't use -[NSProcessInfo operatingSystemVersionString] because it has too much stuff we don't want.
616 int major = callGestalt(gestaltSystemVersionMajor);
619 int minor = callGestalt(gestaltSystemVersionMinor);
620 int bugFix = callGestalt(gestaltSystemVersionBugFix);
622 return [[NSString alloc] initWithFormat:@"%d_%d_%d", major, minor, bugFix];
624 return [[NSString alloc] initWithFormat:@"%d_%d", major, minor];
625 return [[NSString alloc] initWithFormat:@"%d", major];
628 static NSString *createUserVisibleWebKitVersionString()
630 // If the version is 4 digits long or longer, then the first digit represents
631 // the version of the OS. Our user agent string should not include this first digit,
632 // so strip it off and report the rest as the version. <rdar://problem/4997547>
633 NSString *fullVersion = [[NSBundle bundleForClass:[WebView class]] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey];
634 NSRange nonDigitRange = [fullVersion rangeOfCharacterFromSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]];
635 if (nonDigitRange.location == NSNotFound && [fullVersion length] >= 4)
636 return [[fullVersion substringFromIndex:1] copy];
637 if (nonDigitRange.location != NSNotFound && nonDigitRange.location >= 4)
638 return [[fullVersion substringFromIndex:1] copy];
639 return [fullVersion copy];
642 + (NSString *)_standardUserAgentWithApplicationName:(NSString *)applicationName
644 // Note: Do *not* move the initialization of osVersion nor webKitVersion into the declaration.
645 // Garbage collection won't correctly mark the global variable in that case <rdar://problem/5733674>.
646 static NSString *osVersion;
647 static NSString *webKitVersion;
649 osVersion = createMacOSXVersionString();
651 webKitVersion = createUserVisibleWebKitVersionString();
652 NSString *language = [NSUserDefaults _webkit_preferredLanguageCode];
653 if ([applicationName length])
654 return [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; U; " PROCESSOR " Mac OS X %@; %@) AppleWebKit/%@ (KHTML, like Gecko) %@", osVersion, language, webKitVersion, applicationName];
655 return [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; U; " PROCESSOR " Mac OS X %@; %@) AppleWebKit/%@ (KHTML, like Gecko)", osVersion, language, webKitVersion];
658 static void WebKitInitializeApplicationCachePathIfNecessary()
660 static BOOL initialized = NO;
664 NSString *appName = [[NSBundle mainBundle] bundleIdentifier];
666 appName = [[NSProcessInfo processInfo] processName];
670 NSString* cacheDir = [NSString _webkit_localCacheDirectoryWithBundleIdentifier:appName];
672 cacheStorage().setCacheDirectory(cacheDir);
676 - (void)_registerDraggedTypes
678 NSArray *editableTypes = [WebHTMLView _insertablePasteboardTypes];
679 NSArray *URLTypes = [NSPasteboard _web_dragTypesForURL];
680 NSMutableSet *types = [[NSMutableSet alloc] initWithArray:editableTypes];
681 [types addObjectsFromArray:URLTypes];
682 [self registerForDraggedTypes:[types allObjects]];
686 - (BOOL)_usesDocumentViews
688 return _private->useDocumentViews;
691 - (void)_commonInitializationWithFrameName:(NSString *)frameName groupName:(NSString *)groupName usesDocumentViews:(BOOL)usesDocumentViews
693 WebCoreThreadViolationCheck();
696 WTF::RefCountedLeakCounter::suppressMessages(webViewIsOpen);
699 WebPreferences *standardPreferences = [WebPreferences standardPreferences];
700 [standardPreferences willAddToWebView];
702 _private->preferences = [standardPreferences retain];
703 _private->catchesDelegateExceptions = YES;
704 _private->mainFrameDocumentReady = NO;
705 _private->drawsBackground = YES;
706 _private->smartInsertDeleteEnabled = YES;
707 _private->backgroundColor = [[NSColor whiteColor] retain];
708 _private->useDocumentViews = usesDocumentViews;
710 WebFrameView *frameView = nil;
711 if (_private->useDocumentViews) {
712 NSRect f = [self frame];
713 frameView = [[WebFrameView alloc] initWithFrame: NSMakeRect(0,0,f.size.width,f.size.height)];
714 [frameView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
715 [self addSubview:frameView];
719 static bool didOneTimeInitialization = false;
720 if (!didOneTimeInitialization) {
721 WebKitInitializeLoggingChannelsIfNecessary();
722 WebCore::InitializeLoggingChannelsIfNecessary();
723 [WebHistoryItem initWindowWatcherIfNecessary];
724 WebKitInitializeDatabasesIfNecessary();
725 WebKitInitializeApplicationCachePathIfNecessary();
726 patchMailRemoveAttributesMethod();
727 didOneTimeInitialization = true;
730 _private->page = new Page(new WebChromeClient(self), new WebContextMenuClient(self), new WebEditorClient(self), new WebDragClient(self), new WebInspectorClient(self));
732 _private->page->settings()->setLocalStorageDatabasePath([[self preferences] _localStorageDatabasePath]);
734 [WebFrame _createMainFrameWithPage:_private->page frameName:frameName frameView:frameView];
736 #ifndef BUILDING_ON_TIGER
737 if (WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_LOADING_DURING_COMMON_RUNLOOP_MODES))
738 [self scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
740 [self scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
743 [self _addToAllWebViewsSet];
744 [self setGroupName:groupName];
746 // If there's already a next key view (e.g., from a nib), wire it up to our
747 // contained frame view. In any case, wire our next key view up to the our
748 // contained frame view. This works together with our becomeFirstResponder
749 // and setNextKeyView overrides.
750 NSView *nextKeyView = [self nextKeyView];
751 if (nextKeyView && nextKeyView != frameView)
752 [frameView setNextKeyView:nextKeyView];
753 [super setNextKeyView:frameView];
757 [self _registerDraggedTypes];
759 WebPreferences *prefs = [self preferences];
760 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:)
761 name:WebPreferencesChangedNotification object:prefs];
763 // Post a notification so the WebCore settings update.
764 [[self preferences] _postPreferencesChangesNotification];
766 if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_LOCAL_RESOURCE_SECURITY_RESTRICTION)) {
767 // Originally, we allowed all local loads.
768 FrameLoader::setLocalLoadPolicy(FrameLoader::AllowLocalLoadsForAll);
769 } else if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_MORE_STRICT_LOCAL_RESOURCE_SECURITY_RESTRICTION)) {
770 // Later, we allowed local loads for local URLs and documents loaded
771 // with substitute data.
772 FrameLoader::setLocalLoadPolicy(FrameLoader::AllowLocalLoadsForLocalAndSubstituteData);
776 - (id)_initWithFrame:(NSRect)f frameName:(NSString *)frameName groupName:(NSString *)groupName usesDocumentViews:(BOOL)usesDocumentViews
778 self = [super initWithFrame:f];
782 #ifdef ENABLE_WEBKIT_UNSET_DYLD_FRAMEWORK_PATH
783 // DYLD_FRAMEWORK_PATH is used so Safari will load the development version of WebKit, which
784 // may not work with other WebKit applications. Unsetting DYLD_FRAMEWORK_PATH removes the
785 // need for Safari to unset it to prevent it from being passed to applications it launches.
786 // Unsetting it when a WebView is first created is as good a place as any.
787 // See <http://bugs.webkit.org/show_bug.cgi?id=4286> for more details.
788 if (getenv("WEBKIT_UNSET_DYLD_FRAMEWORK_PATH")) {
789 unsetenv("DYLD_FRAMEWORK_PATH");
790 unsetenv("WEBKIT_UNSET_DYLD_FRAMEWORK_PATH");
794 _private = [[WebViewPrivate alloc] init];
795 [self _commonInitializationWithFrameName:frameName groupName:groupName usesDocumentViews:usesDocumentViews];
796 [self setMaintainsBackForwardList: YES];
800 - (void)_boundsChanged
802 Frame* frame = core([self mainFrame]);
803 IntSize oldSize = frame->view()->frameRect().size();
804 frame->view()->resize([self bounds].size.width, [self bounds].size.height);
805 if (oldSize != frame->view()->frameRect().size())
806 [self setNeedsDisplay: YES];
809 - (BOOL)_mustDrawUnionedRect:(NSRect)rect singleRects:(const NSRect *)rects count:(NSInteger)count
811 // If count == 0 here, use the rect passed in for drawing. This is a workaround for:
812 // <rdar://problem/3908282> REGRESSION (Mail): No drag image dragging selected text in Blot and Mail
813 // The reason for the workaround is that this method is called explicitly from the code
814 // to generate a drag image, and at that time, getRectsBeingDrawn:count: will return a zero count.
815 const int cRectThreshold = 10;
816 const float cWastedSpaceThreshold = 0.75f;
817 BOOL useUnionedRect = (count <= 1) || (count > cRectThreshold);
818 if (!useUnionedRect) {
819 // Attempt to guess whether or not we should use the unioned rect or the individual rects.
820 // We do this by computing the percentage of "wasted space" in the union. If that wasted space
821 // is too large, then we will do individual rect painting instead.
822 float unionPixels = (rect.size.width * rect.size.height);
823 float singlePixels = 0;
824 for (int i = 0; i < count; ++i)
825 singlePixels += rects[i].size.width * rects[i].size.height;
826 float wastedSpace = 1 - (singlePixels / unionPixels);
827 if (wastedSpace <= cWastedSpaceThreshold)
828 useUnionedRect = YES;
830 return useUnionedRect;
833 - (void)drawSingleRect:(NSRect)rect
835 ASSERT(!_private->useDocumentViews);
837 [NSGraphicsContext saveGraphicsState];
841 [[self mainFrame] _drawRect:rect contentsOnly:NO];
843 WebView *webView = [self _webView];
844 [[webView _UIDelegateForwarder] webView:webView didDrawRect:rect];
846 if (WebNodeHighlight *currentHighlight = [webView currentNodeHighlight])
847 [currentHighlight setNeedsUpdateInTargetViewRect:rect];
849 [NSGraphicsContext restoreGraphicsState];
850 } @catch (NSException *localException) {
851 [NSGraphicsContext restoreGraphicsState];
852 LOG_ERROR("Exception caught while drawing: %@", localException);
853 [localException raise];
859 return _private && !_private->useDocumentViews;
862 #ifndef BUILDING_ON_TIGER
866 if (!_private->useDocumentViews) {
867 Frame* frame = core([self mainFrame]);
868 if (frame && frame->view())
869 frame->view()->layoutIfNeededRecursive();
871 [super viewWillDraw];
877 - (void)drawRect:(NSRect)rect
879 if (_private->useDocumentViews)
880 return [super drawRect:rect];
882 ASSERT_MAIN_THREAD();
886 [self getRectsBeingDrawn:&rects count:&count];
889 if ([self _mustDrawUnionedRect:rect singleRects:rects count:count])
890 [self drawSingleRect:rect];
892 for (int i = 0; i < count; ++i)
893 [self drawSingleRect:rects[i]];
896 + (NSArray *)_supportedMIMETypes
898 // Load the plug-in DB allowing plug-ins to install types.
899 [WebPluginDatabase sharedDatabase];
900 return [[WebFrameView _viewTypesAllowImageTypeOmission:NO] allKeys];
903 + (NSArray *)_supportedFileExtensions
905 NSMutableSet *extensions = [[NSMutableSet alloc] init];
906 NSArray *MIMETypes = [self _supportedMIMETypes];
907 NSEnumerator *enumerator = [MIMETypes objectEnumerator];
909 while ((MIMEType = [enumerator nextObject]) != nil) {
910 NSArray *extensionsForType = WKGetExtensionsForMIMEType(MIMEType);
911 if (extensionsForType) {
912 [extensions addObjectsFromArray:extensionsForType];
915 NSArray *uniqueExtensions = [extensions allObjects];
916 [extensions release];
917 return uniqueExtensions;
920 + (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType
922 MIMEType = [MIMEType lowercaseString];
923 Class viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:YES] _webkit_objectForMIMEType:MIMEType];
924 Class repClass = [[WebDataSource _repTypesAllowImageTypeOmission:YES] _webkit_objectForMIMEType:MIMEType];
926 if (!viewClass || !repClass || [[WebPDFView supportedMIMETypes] containsObject:MIMEType]) {
927 // Our optimization to avoid loading the plug-in DB and image types for the HTML case failed.
928 // Load the plug-in DB allowing plug-ins to install types.
929 [WebPluginDatabase sharedDatabase];
931 // Load the image types and get the view class and rep class. This should be the fullest picture of all handled types.
932 viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:NO] _webkit_objectForMIMEType:MIMEType];
933 repClass = [[WebDataSource _repTypesAllowImageTypeOmission:NO] _webkit_objectForMIMEType:MIMEType];
936 if (viewClass && repClass) {
937 // Special-case WebHTMLView for text types that shouldn't be shown.
938 if (viewClass == [WebHTMLView class] &&
939 repClass == [WebHTMLRepresentation class] &&
940 [[WebHTMLView unsupportedTextMIMETypes] containsObject:MIMEType]) {
953 - (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType
955 if ([[self class] _viewClass:vClass andRepresentationClass:rClass forMIMEType:MIMEType])
958 if (_private->pluginDatabase) {
959 WebBasePluginPackage *pluginPackage = [_private->pluginDatabase pluginForMIMEType:MIMEType];
962 *vClass = [WebHTMLView class];
964 *rClass = [WebHTMLRepresentation class];
972 + (void)_setAlwaysUseATSU:(BOOL)f
974 [self _setAlwaysUsesComplexTextCodePath:f];
977 + (void)_setAlwaysUsesComplexTextCodePath:(BOOL)f
979 WebCoreSetAlwaysUsesComplexTextCodePath(f);
982 + (BOOL)canShowFile:(NSString *)path
984 return [[self class] canShowMIMEType:[WebView _MIMETypeForFile:path]];
987 + (NSString *)suggestedFileExtensionForMIMEType:(NSString *)type
989 return WKGetPreferredExtensionForMIMEType(type);
994 return !_private || _private->closed;
997 - (void)_closePluginDatabases
999 pluginDatabaseClientCount--;
1001 // Close both sets of plug-in databases because plug-ins need an opportunity to clean up files, etc.
1003 // Unload the WebView local plug-in database.
1004 if (_private->pluginDatabase) {
1005 [_private->pluginDatabase destroyAllPluginInstanceViews];
1006 [_private->pluginDatabase close];
1007 [_private->pluginDatabase release];
1008 _private->pluginDatabase = nil;
1011 // Keep the global plug-in database active until the app terminates to avoid having to reload plug-in bundles.
1012 if (!pluginDatabaseClientCount && applicationIsTerminating)
1013 [WebPluginDatabase closeSharedDatabase];
1016 - (void)_closeWithFastTeardown
1019 WTF::RefCountedLeakCounter::suppressMessages("At least one WebView was closed with fast teardown.");
1022 // Dispatch unload events.
1023 // FIXME: Shouldn't have to use a RefPtr here -- keeping the frame alive while stopping it
1024 // should be WebCore's responsibility -- but we do as of the time this comment was written.
1025 RefPtr<Frame> mainFrame = core([self mainFrame]);
1026 if (mainFrame && mainFrame->page() && mainFrame->page()->pendingUnloadEventCount())
1027 mainFrame->loader()->stopLoading(true);
1029 _private->closed = YES;
1031 [self _closePluginDatabases];
1034 // _close is here only for backward compatibility; clients and subclasses should use
1035 // public method -close instead.
1038 if (!_private || _private->closed)
1042 WTF::RefCountedLeakCounter::cancelMessageSuppression(webViewIsOpen);
1045 WebPreferences *preferences = _private->preferences;
1046 BOOL fullDocumentTeardown = [preferences fullDocumentTeardownEnabled];
1048 // To quit the apps fast we skip document teardown. Two exceptions:
1049 // 1) plugins need to be destroyed and unloaded
1050 // 2) unload events need to be called
1051 if (applicationIsTerminating && !fullDocumentTeardown) {
1052 [self _closeWithFastTeardown];
1056 if (Frame* mainFrame = core([self mainFrame]))
1057 mainFrame->loader()->detachFromParent();
1059 [self _removeFromAllWebViewsSet];
1060 [self setHostWindow:nil];
1062 [self setDownloadDelegate:nil];
1063 [self setEditingDelegate:nil];
1064 [self setFrameLoadDelegate:nil];
1065 [self setPolicyDelegate:nil];
1066 [self setResourceLoadDelegate:nil];
1067 [self setScriptDebugDelegate:nil];
1068 [self setUIDelegate:nil];
1070 [_private->inspector webViewClosed];
1072 // setHostWindow:nil must be called before this value is set (see 5408186)
1073 _private->closed = YES;
1075 // To avoid leaks, call removeDragCaret in case it wasn't called after moveDragCaretToPoint.
1076 [self removeDragCaret];
1078 // Deleteing the WebCore::Page will clear the page cache so we call destroy on
1079 // all the plug-ins in the page cache to break any retain cycles.
1080 // See comment in HistoryItem::releaseAllPendingPageCaches() for more information.
1081 delete _private->page;
1084 if (_private->hasSpellCheckerDocumentTag) {
1085 [[NSSpellChecker sharedSpellChecker] closeSpellDocumentWithTag:_private->spellCheckerDocumentTag];
1086 _private->hasSpellCheckerDocumentTag = NO;
1089 [[NSDistributedNotificationCenter defaultCenter] removeObserver:self];
1090 [[NSNotificationCenter defaultCenter] removeObserver:self];
1092 [WebPreferences _removeReferenceForIdentifier:[self preferencesIdentifier]];
1094 _private->preferences = nil;
1095 [preferences didRemoveFromWebView];
1096 [preferences release];
1098 [self _closePluginDatabases];
1101 // Need this to make leak messages accurate.
1102 if (applicationIsTerminating) {
1103 gcController().garbageCollectNow();
1104 [WebCache setDisabled:YES];
1109 + (NSString *)_MIMETypeForFile:(NSString *)path
1111 NSString *extension = [path pathExtension];
1112 NSString *MIMEType = nil;
1114 // Get the MIME type from the extension.
1115 if ([extension length] != 0) {
1116 MIMEType = WKGetMIMETypeForExtension(extension);
1119 // If we can't get a known MIME type from the extension, sniff.
1120 if ([MIMEType length] == 0 || [MIMEType isEqualToString:@"application/octet-stream"]) {
1121 NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:path];
1122 NSData *data = [handle readDataOfLength:WEB_GUESS_MIME_TYPE_PEEK_LENGTH];
1124 if ([data length] != 0) {
1125 MIMEType = [data _webkit_guessedMIMEType];
1127 if ([MIMEType length] == 0) {
1128 MIMEType = @"application/octet-stream";
1135 - (WebDownload *)_downloadURL:(NSURL *)URL
1139 NSURLRequest *request = [[NSURLRequest alloc] initWithURL:URL];
1140 WebDownload *download = [WebDownload _downloadWithRequest:request
1141 delegate:_private->downloadDelegate
1148 - (WebView *)_openNewWindowWithRequest:(NSURLRequest *)request
1150 NSDictionary *features = [[NSDictionary alloc] init];
1151 WebView *newWindowWebView = [[self _UIDelegateForwarder] webView:self
1152 createWebViewWithRequest:nil
1153 windowFeatures:features];
1155 if (!newWindowWebView)
1158 CallUIDelegate(newWindowWebView, @selector(webViewShow:));
1159 return newWindowWebView;
1162 - (WebInspector *)inspector
1164 if (!_private->inspector)
1165 _private->inspector = [[WebInspector alloc] initWithWebView:self];
1166 return _private->inspector;
1169 - (WebCore::Page*)page
1171 return _private->page;
1174 - (NSMenu *)_menuForElement:(NSDictionary *)element defaultItems:(NSArray *)items
1176 NSArray *defaultMenuItems = [[WebDefaultUIDelegate sharedUIDelegate] webView:self contextMenuItemsForElement:element defaultMenuItems:items];
1178 NSArray *menuItems = CallUIDelegate(self, @selector(webView:contextMenuItemsForElement:defaultMenuItems:), element, defaultMenuItems);
1182 unsigned count = [menuItems count];
1186 NSMenu *menu = [[NSMenu alloc] init];
1187 for (unsigned i = 0; i < count; i++)
1188 [menu addItem:[menuItems objectAtIndex:i]];
1190 return [menu autorelease];
1193 - (void)_mouseDidMoveOverElement:(NSDictionary *)dictionary modifierFlags:(NSUInteger)modifierFlags
1195 // We originally intended to call this delegate method sometimes with a nil dictionary, but due to
1196 // a bug dating back to WebKit 1.0 this delegate was never called with nil! Unfortunately we can't
1197 // start calling this with nil since it will break Adobe Help Viewer, and possibly other clients.
1200 CallUIDelegate(self, @selector(webView:mouseDidMoveOverElement:modifierFlags:), dictionary, modifierFlags);
1203 - (void)_loadBackForwardListFromOtherView:(WebView *)otherView
1205 if (!_private->page)
1208 if (!otherView->_private->page)
1211 // It turns out the right combination of behavior is done with the back/forward load
1212 // type. (See behavior matrix at the top of WebFramePrivate.) So we copy all the items
1213 // in the back forward list, and go to the current one.
1215 BackForwardList* backForwardList = _private->page->backForwardList();
1216 ASSERT(!backForwardList->currentItem()); // destination list should be empty
1218 BackForwardList* otherBackForwardList = otherView->_private->page->backForwardList();
1219 if (!otherBackForwardList->currentItem())
1220 return; // empty back forward list, bail
1222 HistoryItem* newItemToGoTo = 0;
1224 int lastItemIndex = otherBackForwardList->forwardListCount();
1225 for (int i = -otherBackForwardList->backListCount(); i <= lastItemIndex; ++i) {
1227 // If this item is showing , save away its current scroll and form state,
1228 // since that might have changed since loading and it is normally not saved
1229 // until we leave that page.
1230 otherView->_private->page->mainFrame()->loader()->saveDocumentAndScrollState();
1232 RefPtr<HistoryItem> newItem = otherBackForwardList->itemAtIndex(i)->copy();
1234 newItemToGoTo = newItem.get();
1235 backForwardList->addItem(newItem.release());
1238 ASSERT(newItemToGoTo);
1239 _private->page->goToItem(newItemToGoTo, FrameLoadTypeIndexedBackForward);
1242 - (void)_setFormDelegate: (id<WebFormDelegate>)delegate
1244 _private->formDelegate = delegate;
1247 - (id<WebFormDelegate>)_formDelegate
1249 return _private->formDelegate;
1252 - (BOOL)_needsAdobeFrameReloadingQuirk
1254 static BOOL checked = NO;
1255 static BOOL needsQuirk = NO;
1260 needsQuirk = WKAppVersionCheckLessThan(@"com.adobe.Acrobat", -1, 9.0)
1261 || WKAppVersionCheckLessThan(@"com.adobe.Acrobat.Pro", -1, 9.0)
1262 || WKAppVersionCheckLessThan(@"com.adobe.Reader", -1, 9.0)
1263 || WKAppVersionCheckLessThan(@"com.adobe.distiller", -1, 9.0)
1264 || WKAppVersionCheckLessThan(@"com.adobe.Contribute", -1, 4.2)
1265 || WKAppVersionCheckLessThan(@"com.adobe.dreamweaver-9.0", -1, 9.1)
1266 || WKAppVersionCheckLessThan(@"com.macromedia.fireworks", -1, 9.1)
1267 || WKAppVersionCheckLessThan(@"com.adobe.InCopy", -1, 5.1)
1268 || WKAppVersionCheckLessThan(@"com.adobe.InDesign", -1, 5.1)
1269 || WKAppVersionCheckLessThan(@"com.adobe.Soundbooth", -1, 2);
1275 - (BOOL)_needsKeyboardEventDisambiguationQuirks
1277 static BOOL checked = NO;
1278 static BOOL needsQuirks = NO;
1283 needsQuirks = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_IE_COMPATIBLE_KEYBOARD_EVENT_DISPATCH)
1284 && ![[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.Safari"];
1290 - (void)_preferencesChangedNotification:(NSNotification *)notification
1292 WebPreferences *preferences = (WebPreferences *)[notification object];
1293 ASSERT(preferences == [self preferences]);
1295 if (!_private->userAgentOverridden)
1296 _private->userAgent = String();
1298 // Cache this value so we don't have to read NSUserDefaults on each page load
1299 _private->useSiteSpecificSpoofing = [preferences _useSiteSpecificSpoofing];
1301 // Update corresponding WebCore Settings object.
1302 if (!_private->page)
1305 Settings* settings = _private->page->settings();
1307 settings->setCursiveFontFamily([preferences cursiveFontFamily]);
1308 settings->setDefaultFixedFontSize([preferences defaultFixedFontSize]);
1309 settings->setDefaultFontSize([preferences defaultFontSize]);
1310 settings->setDefaultTextEncodingName([preferences defaultTextEncodingName]);
1311 settings->setFantasyFontFamily([preferences fantasyFontFamily]);
1312 settings->setFixedFontFamily([preferences fixedFontFamily]);
1313 settings->setForceFTPDirectoryListings([preferences _forceFTPDirectoryListings]);
1314 settings->setFTPDirectoryTemplatePath([preferences _ftpDirectoryTemplatePath]);
1315 settings->setLocalStorageDatabasePath([preferences _localStorageDatabasePath]);
1316 settings->setJavaEnabled([preferences isJavaEnabled]);
1317 settings->setJavaScriptEnabled([preferences isJavaScriptEnabled]);
1318 settings->setWebSecurityEnabled([preferences isWebSecurityEnabled]);
1319 settings->setAllowUniversalAccessFromFileURLs([preferences allowUniversalAccessFromFileURLs]);
1320 settings->setJavaScriptCanOpenWindowsAutomatically([preferences javaScriptCanOpenWindowsAutomatically]);
1321 settings->setMinimumFontSize([preferences minimumFontSize]);
1322 settings->setMinimumLogicalFontSize([preferences minimumLogicalFontSize]);
1323 settings->setPluginsEnabled([preferences arePlugInsEnabled]);
1324 settings->setDatabasesEnabled([preferences databasesEnabled]);
1325 settings->setLocalStorageEnabled([preferences localStorageEnabled]);
1326 settings->setPrivateBrowsingEnabled([preferences privateBrowsingEnabled]);
1327 settings->setSansSerifFontFamily([preferences sansSerifFontFamily]);
1328 settings->setSerifFontFamily([preferences serifFontFamily]);
1329 settings->setStandardFontFamily([preferences standardFontFamily]);
1330 settings->setLoadsImagesAutomatically([preferences loadsImagesAutomatically]);
1331 settings->setShouldPrintBackgrounds([preferences shouldPrintBackgrounds]);
1332 settings->setTextAreasAreResizable([preferences textAreasAreResizable]);
1333 settings->setShrinksStandaloneImagesToFit([preferences shrinksStandaloneImagesToFit]);
1334 settings->setEditableLinkBehavior(core([preferences editableLinkBehavior]));
1335 settings->setTextDirectionSubmenuInclusionBehavior(core([preferences textDirectionSubmenuInclusionBehavior]));
1336 settings->setDOMPasteAllowed([preferences isDOMPasteAllowed]);
1337 settings->setUsesPageCache([self usesPageCache]);
1338 settings->setShowsURLsInToolTips([preferences showsURLsInToolTips]);
1339 settings->setDeveloperExtrasEnabled([preferences developerExtrasEnabled]);
1340 settings->setAuthorAndUserStylesEnabled([preferences authorAndUserStylesEnabled]);
1341 settings->setApplicationChromeMode([preferences applicationChromeModeEnabled]);
1342 if ([preferences userStyleSheetEnabled]) {
1343 NSString* location = [[preferences userStyleSheetLocation] _web_originalDataAsString];
1344 settings->setUserStyleSheetLocation([NSURL URLWithString:(location ? location : @"")]);
1346 settings->setUserStyleSheetLocation([NSURL URLWithString:@""]);
1347 settings->setNeedsAdobeFrameReloadingQuirk([self _needsAdobeFrameReloadingQuirk]);
1348 settings->setNeedsKeyboardEventDisambiguationQuirks([self _needsKeyboardEventDisambiguationQuirks]);
1349 settings->setNeedsSiteSpecificQuirks(_private->useSiteSpecificSpoofing);
1350 settings->setWebArchiveDebugModeEnabled([preferences webArchiveDebugModeEnabled]);
1351 settings->disableRangeMutationForOldAppleMail(WKAppVersionCheckLessThan(@"com.apple.mail", -1, 4.0));
1352 settings->setOfflineWebApplicationCacheEnabled([preferences offlineWebApplicationCacheEnabled]);
1353 settings->setZoomsTextOnly([preferences zoomsTextOnly]);
1354 settings->setEnforceCSSMIMETypeInStrictMode(!WKAppVersionCheckLessThan(@"com.apple.iWeb", -1, 2.1));
1357 static inline IMP getMethod(id o, SEL s)
1359 return [o respondsToSelector:s] ? [o methodForSelector:s] : 0;
1362 - (void)_cacheResourceLoadDelegateImplementations
1364 WebResourceDelegateImplementationCache *cache = &_private->resourceLoadDelegateImplementations;
1365 id delegate = _private->resourceProgressDelegate;
1368 bzero(cache, sizeof(WebResourceDelegateImplementationCache));
1372 cache->didCancelAuthenticationChallengeFunc = getMethod(delegate, @selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:));
1373 cache->didFailLoadingWithErrorFromDataSourceFunc = getMethod(delegate, @selector(webView:resource:didFailLoadingWithError:fromDataSource:));
1374 cache->didFinishLoadingFromDataSourceFunc = getMethod(delegate, @selector(webView:resource:didFinishLoadingFromDataSource:));
1375 cache->didLoadResourceFromMemoryCacheFunc = getMethod(delegate, @selector(webView:didLoadResourceFromMemoryCache:response:length:fromDataSource:));
1376 cache->didReceiveAuthenticationChallengeFunc = getMethod(delegate, @selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:));
1377 cache->didReceiveContentLengthFunc = getMethod(delegate, @selector(webView:resource:didReceiveContentLength:fromDataSource:));
1378 cache->didReceiveResponseFunc = getMethod(delegate, @selector(webView:resource:didReceiveResponse:fromDataSource:));
1379 cache->identifierForRequestFunc = getMethod(delegate, @selector(webView:identifierForInitialRequest:fromDataSource:));
1380 cache->plugInFailedWithErrorFunc = getMethod(delegate, @selector(webView:plugInFailedWithError:dataSource:));
1381 cache->willCacheResponseFunc = getMethod(delegate, @selector(webView:resource:willCacheResponse:fromDataSource:));
1382 cache->willSendRequestFunc = getMethod(delegate, @selector(webView:resource:willSendRequest:redirectResponse:fromDataSource:));
1383 cache->shouldUseCredentialStorageFunc = getMethod(delegate, @selector(webView:resource:shouldUseCredentialStorageForDataSource:));
1386 WebResourceDelegateImplementationCache* WebViewGetResourceLoadDelegateImplementations(WebView *webView)
1388 static WebResourceDelegateImplementationCache empty;
1391 return &webView->_private->resourceLoadDelegateImplementations;
1394 - (void)_cacheFrameLoadDelegateImplementations
1396 WebFrameLoadDelegateImplementationCache *cache = &_private->frameLoadDelegateImplementations;
1397 id delegate = _private->frameLoadDelegate;
1400 bzero(cache, sizeof(WebFrameLoadDelegateImplementationCache));
1404 cache->didCancelClientRedirectForFrameFunc = getMethod(delegate, @selector(webView:didCancelClientRedirectForFrame:));
1405 cache->didChangeLocationWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didChangeLocationWithinPageForFrame:));
1406 cache->didClearWindowObjectForFrameFunc = getMethod(delegate, @selector(webView:didClearWindowObject:forFrame:));
1407 cache->didCommitLoadForFrameFunc = getMethod(delegate, @selector(webView:didCommitLoadForFrame:));
1408 cache->didFailLoadWithErrorForFrameFunc = getMethod(delegate, @selector(webView:didFailLoadWithError:forFrame:));
1409 cache->didFailProvisionalLoadWithErrorForFrameFunc = getMethod(delegate, @selector(webView:didFailProvisionalLoadWithError:forFrame:));
1410 cache->didFinishDocumentLoadForFrameFunc = getMethod(delegate, @selector(webView:didFinishDocumentLoadForFrame:));
1411 cache->didFinishLoadForFrameFunc = getMethod(delegate, @selector(webView:didFinishLoadForFrame:));
1412 cache->didFirstLayoutInFrameFunc = getMethod(delegate, @selector(webView:didFirstLayoutInFrame:));
1413 cache->didFirstVisuallyNonEmptyLayoutInFrameFunc = getMethod(delegate, @selector(webView:didFirstVisuallyNonEmptyLayoutInFrame:));
1414 cache->didHandleOnloadEventsForFrameFunc = getMethod(delegate, @selector(webView:didHandleOnloadEventsForFrame:));
1415 cache->didReceiveIconForFrameFunc = getMethod(delegate, @selector(webView:didReceiveIcon:forFrame:));
1416 cache->didReceiveServerRedirectForProvisionalLoadForFrameFunc = getMethod(delegate, @selector(webView:didReceiveServerRedirectForProvisionalLoadForFrame:));
1417 cache->didReceiveTitleForFrameFunc = getMethod(delegate, @selector(webView:didReceiveTitle:forFrame:));
1418 cache->didStartProvisionalLoadForFrameFunc = getMethod(delegate, @selector(webView:didStartProvisionalLoadForFrame:));
1419 cache->willCloseFrameFunc = getMethod(delegate, @selector(webView:willCloseFrame:));
1420 cache->willPerformClientRedirectToURLDelayFireDateForFrameFunc = getMethod(delegate, @selector(webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:));
1421 cache->windowScriptObjectAvailableFunc = getMethod(delegate, @selector(webView:windowScriptObjectAvailable:));
1424 WebFrameLoadDelegateImplementationCache* WebViewGetFrameLoadDelegateImplementations(WebView *webView)
1426 static WebFrameLoadDelegateImplementationCache empty;
1429 return &webView->_private->frameLoadDelegateImplementations;
1432 - (void)_cacheScriptDebugDelegateImplementations
1434 WebScriptDebugDelegateImplementationCache *cache = &_private->scriptDebugDelegateImplementations;
1435 id delegate = _private->scriptDebugDelegate;
1438 bzero(cache, sizeof(WebScriptDebugDelegateImplementationCache));
1442 cache->didParseSourceFunc = getMethod(delegate, @selector(webView:didParseSource:baseLineNumber:fromURL:sourceId:forWebFrame:));
1443 if (cache->didParseSourceFunc)
1444 cache->didParseSourceExpectsBaseLineNumber = YES;
1446 cache->didParseSourceFunc = getMethod(delegate, @selector(webView:didParseSource:fromURL:sourceId:forWebFrame:));
1448 cache->failedToParseSourceFunc = getMethod(delegate, @selector(webView:failedToParseSource:baseLineNumber:fromURL:withError:forWebFrame:));
1449 cache->didEnterCallFrameFunc = getMethod(delegate, @selector(webView:didEnterCallFrame:sourceId:line:forWebFrame:));
1450 cache->willExecuteStatementFunc = getMethod(delegate, @selector(webView:willExecuteStatement:sourceId:line:forWebFrame:));
1451 cache->willLeaveCallFrameFunc = getMethod(delegate, @selector(webView:willLeaveCallFrame:sourceId:line:forWebFrame:));
1452 cache->exceptionWasRaisedFunc = getMethod(delegate, @selector(webView:exceptionWasRaised:sourceId:line:forWebFrame:));
1455 WebScriptDebugDelegateImplementationCache* WebViewGetScriptDebugDelegateImplementations(WebView *webView)
1457 static WebScriptDebugDelegateImplementationCache empty;
1460 return &webView->_private->scriptDebugDelegateImplementations;
1463 - (id)_policyDelegateForwarder
1465 if (!_private->policyDelegateForwarder)
1466 _private->policyDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->policyDelegate defaultTarget:[WebDefaultPolicyDelegate sharedPolicyDelegate] catchExceptions:_private->catchesDelegateExceptions];
1467 return _private->policyDelegateForwarder;
1470 - (id)_UIDelegateForwarder
1472 if (!_private->UIDelegateForwarder)
1473 _private->UIDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->UIDelegate defaultTarget:[WebDefaultUIDelegate sharedUIDelegate] catchExceptions:_private->catchesDelegateExceptions];
1474 return _private->UIDelegateForwarder;
1477 - (id)_editingDelegateForwarder
1479 // This can be called during window deallocation by QTMovieView in the QuickTime Cocoa Plug-in.
1480 // Not sure if that is a bug or not.
1484 if (!_private->editingDelegateForwarder)
1485 _private->editingDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->editingDelegate defaultTarget:[WebDefaultEditingDelegate sharedEditingDelegate] catchExceptions:_private->catchesDelegateExceptions];
1486 return _private->editingDelegateForwarder;
1489 - (void)_closeWindow
1491 [[self _UIDelegateForwarder] webViewClose:self];
1494 + (void)_unregisterViewClassAndRepresentationClassForMIMEType:(NSString *)MIMEType
1496 [[WebFrameView _viewTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType];
1497 [[WebDataSource _repTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType];
1499 // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
1500 // in the WebCore MIMEType registry. For now we're doing this in a safe, limited manner
1501 // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
1502 MIMETypeRegistry::getSupportedNonImageMIMETypes().remove(MIMEType);
1505 + (void)_registerViewClass:(Class)viewClass representationClass:(Class)representationClass forURLScheme:(NSString *)URLScheme
1507 NSString *MIMEType = [self _generatedMIMETypeForURLScheme:URLScheme];
1508 [self registerViewClass:viewClass representationClass:representationClass forMIMEType:MIMEType];
1510 // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
1511 // in the WebCore MIMEType registry. For now we're doing this in a safe, limited manner
1512 // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
1513 if ([viewClass class] == [WebHTMLView class])
1514 MIMETypeRegistry::getSupportedNonImageMIMETypes().add(MIMEType);
1516 // This is used to make _representationExistsForURLScheme faster.
1517 // Without this set, we'd have to create the MIME type each time.
1518 if (schemesWithRepresentationsSet == nil) {
1519 schemesWithRepresentationsSet = [[NSMutableSet alloc] init];
1521 [schemesWithRepresentationsSet addObject:[[[URLScheme lowercaseString] copy] autorelease]];
1524 + (NSString *)_generatedMIMETypeForURLScheme:(NSString *)URLScheme
1526 return [@"x-apple-web-kit/" stringByAppendingString:[URLScheme lowercaseString]];
1529 + (BOOL)_representationExistsForURLScheme:(NSString *)URLScheme
1531 return [schemesWithRepresentationsSet containsObject:[URLScheme lowercaseString]];
1534 + (BOOL)_canHandleRequest:(NSURLRequest *)request forMainFrame:(BOOL)forMainFrame
1536 // FIXME: If <rdar://problem/5217309> gets fixed, this check can be removed.
1540 if ([NSURLConnection canHandleRequest:request])
1543 NSString *scheme = [[request URL] scheme];
1545 // Representations for URL schemes work at the top level.
1546 if (forMainFrame && [self _representationExistsForURLScheme:scheme])
1549 return [scheme _webkit_isCaseInsensitiveEqualToString:@"applewebdata"];
1552 + (BOOL)_canHandleRequest:(NSURLRequest *)request
1554 return [self _canHandleRequest:request forMainFrame:YES];
1557 + (NSString *)_decodeData:(NSData *)data
1559 HTMLNames::init(); // this method is used for importing bookmarks at startup, so HTMLNames are likely to be uninitialized yet
1560 RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("text/html"); // bookmark files are HTML
1561 String result = decoder->decode(static_cast<const char*>([data bytes]), [data length]);
1562 result += decoder->flush();
1566 - (void)_pushPerformingProgrammaticFocus
1568 _private->programmaticFocusCount++;
1571 - (void)_popPerformingProgrammaticFocus
1573 _private->programmaticFocusCount--;
1576 - (BOOL)_isPerformingProgrammaticFocus
1578 return _private->programmaticFocusCount != 0;
1581 - (void)_didChangeValueForKey: (NSString *)key
1583 LOG (Bindings, "calling didChangeValueForKey: %@", key);
1584 [self didChangeValueForKey: key];
1587 - (void)_willChangeValueForKey: (NSString *)key
1589 LOG (Bindings, "calling willChangeValueForKey: %@", key);
1590 [self willChangeValueForKey: key];
1593 + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key {
1594 static NSSet *manualNotifyKeys = nil;
1595 if (!manualNotifyKeys)
1596 manualNotifyKeys = [[NSSet alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey,
1597 _WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, _WebMainFrameDocumentKey,
1598 #if USE(ACCELERATED_COMPOSITING)
1599 UsingAcceleratedCompositingProperty, // used by DRT
1602 if ([manualNotifyKeys containsObject:key])
1607 - (NSArray *)_declaredKeys {
1608 static NSArray *declaredKeys = nil;
1610 declaredKeys = [[NSArray alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey,
1611 _WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, _WebMainFrameDocumentKey, nil];
1612 return declaredKeys;
1615 - (void)setObservationInfo:(void *)info
1617 _private->observationInfo = info;
1620 - (void *)observationInfo
1622 return _private->observationInfo;
1625 - (void)_willChangeBackForwardKeys
1627 [self _willChangeValueForKey: _WebCanGoBackKey];
1628 [self _willChangeValueForKey: _WebCanGoForwardKey];
1631 - (void)_didChangeBackForwardKeys
1633 [self _didChangeValueForKey: _WebCanGoBackKey];
1634 [self _didChangeValueForKey: _WebCanGoForwardKey];
1637 - (void)_didStartProvisionalLoadForFrame:(WebFrame *)frame
1639 [self _willChangeBackForwardKeys];
1640 if (frame == [self mainFrame]){
1641 // Force an observer update by sending a will/did.
1642 [self _willChangeValueForKey: _WebIsLoadingKey];
1643 [self _didChangeValueForKey: _WebIsLoadingKey];
1645 [self _willChangeValueForKey: _WebMainFrameURLKey];
1648 [NSApp setWindowsNeedUpdate:YES];
1651 - (void)_didCommitLoadForFrame:(WebFrame *)frame
1653 if (frame == [self mainFrame])
1654 [self _didChangeValueForKey: _WebMainFrameURLKey];
1655 [NSApp setWindowsNeedUpdate:YES];
1658 - (void)_didFinishLoadForFrame:(WebFrame *)frame
1660 [self _didChangeBackForwardKeys];
1661 if (frame == [self mainFrame]){
1662 // Force an observer update by sending a will/did.
1663 [self _willChangeValueForKey: _WebIsLoadingKey];
1664 [self _didChangeValueForKey: _WebIsLoadingKey];
1666 [NSApp setWindowsNeedUpdate:YES];
1669 - (void)_didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
1671 [self _didChangeBackForwardKeys];
1672 if (frame == [self mainFrame]){
1673 // Force an observer update by sending a will/did.
1674 [self _willChangeValueForKey: _WebIsLoadingKey];
1675 [self _didChangeValueForKey: _WebIsLoadingKey];
1677 [NSApp setWindowsNeedUpdate:YES];
1680 - (void)_didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
1682 [self _didChangeBackForwardKeys];
1683 if (frame == [self mainFrame]){
1684 // Force an observer update by sending a will/did.
1685 [self _willChangeValueForKey: _WebIsLoadingKey];
1686 [self _didChangeValueForKey: _WebIsLoadingKey];
1688 [self _didChangeValueForKey: _WebMainFrameURLKey];
1690 [NSApp setWindowsNeedUpdate:YES];
1693 - (NSCachedURLResponse *)_cachedResponseForURL:(NSURL *)URL
1695 NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:URL];
1696 [request _web_setHTTPUserAgent:[self userAgentForURL:URL]];
1697 NSCachedURLResponse *cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:request];
1699 return cachedResponse;
1702 - (void)_writeImageForElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
1704 NSURL *linkURL = [element objectForKey:WebElementLinkURLKey];
1705 DOMElement *domElement = [element objectForKey:WebElementDOMNodeKey];
1706 [pasteboard _web_writeImage:(NSImage *)(domElement ? nil : [element objectForKey:WebElementImageKey])
1708 URL:linkURL ? linkURL : (NSURL *)[element objectForKey:WebElementImageURLKey]
1709 title:[element objectForKey:WebElementImageAltStringKey]
1710 archive:[[element objectForKey:WebElementDOMNodeKey] webArchive]
1715 - (void)_writeLinkElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
1717 [pasteboard _web_writeURL:[element objectForKey:WebElementLinkURLKey]
1718 andTitle:[element objectForKey:WebElementLinkLabelKey]
1722 - (void)_setInitiatedDrag:(BOOL)initiatedDrag
1724 if (!_private->page)
1726 _private->page->dragController()->setDidInitiateDrag(initiatedDrag);
1729 #if ENABLE(DASHBOARD_SUPPORT)
1731 #define DASHBOARD_CONTROL_LABEL @"control"
1733 - (void)_addScrollerDashboardRegions:(NSMutableDictionary *)regions from:(NSArray *)views
1735 // Add scroller regions for NSScroller and KWQScrollBar
1736 int i, count = [views count];
1738 for (i = 0; i < count; i++) {
1739 NSView *aView = [views objectAtIndex:i];
1741 if ([aView isKindOfClass:[NSScroller class]] ||
1742 [aView isKindOfClass:NSClassFromString (@"KWQScrollBar")]) {
1743 NSRect bounds = [aView bounds];
1744 NSRect adjustedBounds;
1745 adjustedBounds.origin = [self convertPoint:bounds.origin fromView:aView];
1746 adjustedBounds.origin.y = [self bounds].size.height - adjustedBounds.origin.y;
1748 // AppKit has horrible hack of placing absent scrollers at -100,-100
1749 if (adjustedBounds.origin.y == -100)
1751 adjustedBounds.size = bounds.size;
1752 NSRect clip = [aView visibleRect];
1753 NSRect adjustedClip;
1754 adjustedClip.origin = [self convertPoint:clip.origin fromView:aView];
1755 adjustedClip.origin.y = [self bounds].size.height - adjustedClip.origin.y;
1756 adjustedClip.size = clip.size;
1757 WebDashboardRegion *aRegion =
1758 [[[WebDashboardRegion alloc] initWithRect:adjustedBounds
1759 clip:adjustedClip type:WebDashboardRegionTypeScrollerRectangle] autorelease];
1760 NSMutableArray *scrollerRegions;
1761 scrollerRegions = [regions objectForKey:DASHBOARD_CONTROL_LABEL];
1762 if (!scrollerRegions) {
1763 scrollerRegions = [NSMutableArray array];
1764 [regions setObject:scrollerRegions forKey:DASHBOARD_CONTROL_LABEL];
1766 [scrollerRegions addObject:aRegion];
1768 [self _addScrollerDashboardRegions:regions from:[aView subviews]];
1772 - (void)_addScrollerDashboardRegions:(NSMutableDictionary *)regions
1774 [self _addScrollerDashboardRegions:regions from:[self subviews]];
1777 - (NSDictionary *)_dashboardRegions
1779 // Only return regions from main frame.
1780 Frame* mainFrame = core([self mainFrame]);
1783 NSMutableDictionary *regions = mainFrame->dashboardRegionsDictionary();
1784 [self _addScrollerDashboardRegions:regions];
1788 - (void)_setDashboardBehavior:(WebDashboardBehavior)behavior to:(BOOL)flag
1790 // FIXME: Remove this blanket assignment once Dashboard and Dashcode implement
1791 // specific support for the backward compatibility mode flag.
1792 if (behavior == WebDashboardBehaviorAllowWheelScrolling && flag == NO && _private->page)
1793 _private->page->settings()->setUsesDashboardBackwardCompatibilityMode(true);
1796 case WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows: {
1797 _private->dashboardBehaviorAlwaysSendMouseEventsToAllWindows = flag;
1800 case WebDashboardBehaviorAlwaysSendActiveNullEventsToPlugIns: {
1801 _private->dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns = flag;
1804 case WebDashboardBehaviorAlwaysAcceptsFirstMouse: {
1805 _private->dashboardBehaviorAlwaysAcceptsFirstMouse = flag;
1808 case WebDashboardBehaviorAllowWheelScrolling: {
1809 _private->dashboardBehaviorAllowWheelScrolling = flag;
1812 case WebDashboardBehaviorUseBackwardCompatibilityMode: {
1814 _private->page->settings()->setUsesDashboardBackwardCompatibilityMode(flag);
1820 - (BOOL)_dashboardBehavior:(WebDashboardBehavior)behavior
1823 case WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows: {
1824 return _private->dashboardBehaviorAlwaysSendMouseEventsToAllWindows;
1826 case WebDashboardBehaviorAlwaysSendActiveNullEventsToPlugIns: {
1827 return _private->dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns;
1829 case WebDashboardBehaviorAlwaysAcceptsFirstMouse: {
1830 return _private->dashboardBehaviorAlwaysAcceptsFirstMouse;
1832 case WebDashboardBehaviorAllowWheelScrolling: {
1833 return _private->dashboardBehaviorAllowWheelScrolling;
1835 case WebDashboardBehaviorUseBackwardCompatibilityMode: {
1836 return _private->page && _private->page->settings()->usesDashboardBackwardCompatibilityMode();
1842 #endif /* ENABLE(DASHBOARD_SUPPORT) */
1844 + (void)_setShouldUseFontSmoothing:(BOOL)f
1846 WebCoreSetShouldUseFontSmoothing(f);
1849 + (BOOL)_shouldUseFontSmoothing
1851 return WebCoreShouldUseFontSmoothing();
1854 + (void)_setUsesTestModeFocusRingColor:(BOOL)f
1856 setUsesTestModeFocusRingColor(f);
1859 + (BOOL)_usesTestModeFocusRingColor
1861 return usesTestModeFocusRingColor();
1864 // This is only used by versions of Safari up to and including 3.0 and should be removed in a future release.
1865 + (NSString *)_minimumRequiredSafariBuildNumber
1870 - (void)setAlwaysShowVerticalScroller:(BOOL)flag
1872 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
1874 [scrollview setVerticalScrollingMode:ScrollbarAlwaysOn andLock:YES];
1876 [scrollview setVerticalScrollingModeLocked:NO];
1877 [scrollview setVerticalScrollingMode:ScrollbarAuto andLock:NO];
1881 - (BOOL)alwaysShowVerticalScroller
1883 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
1884 return [scrollview verticalScrollingModeLocked] && [scrollview verticalScrollingMode] == ScrollbarAlwaysOn;
1887 - (void)setAlwaysShowHorizontalScroller:(BOOL)flag
1889 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
1891 [scrollview setHorizontalScrollingMode:ScrollbarAlwaysOn andLock:YES];
1893 [scrollview setHorizontalScrollingModeLocked:NO];
1894 [scrollview setHorizontalScrollingMode:ScrollbarAuto andLock:NO];
1898 - (void)setProhibitsMainFrameScrolling:(BOOL)prohibits
1900 Frame* mainFrame = core([self mainFrame]);
1902 mainFrame->view()->setProhibitsScrolling(prohibits);
1905 - (BOOL)alwaysShowHorizontalScroller
1907 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
1908 return [scrollview horizontalScrollingModeLocked] && [scrollview horizontalScrollingMode] == ScrollbarAlwaysOn;
1911 - (void)_setInViewSourceMode:(BOOL)flag
1913 Frame* mainFrame = core([self mainFrame]);
1915 mainFrame->setInViewSourceMode(flag);
1918 - (BOOL)_inViewSourceMode
1920 Frame* mainFrame = core([self mainFrame]);
1921 return mainFrame && mainFrame->inViewSourceMode();
1924 - (void)_setUseFastImageScalingMode:(BOOL)flag
1926 if (_private->page && _private->page->inLowQualityImageInterpolationMode() != flag) {
1927 _private->page->setInLowQualityImageInterpolationMode(flag);
1928 [self setNeedsDisplay:YES];
1932 - (BOOL)_inFastImageScalingMode
1935 return _private->page->inLowQualityImageInterpolationMode();
1939 - (BOOL)_cookieEnabled
1942 return _private->page->cookieEnabled();
1946 - (void)_setCookieEnabled:(BOOL)enable
1949 _private->page->setCookieEnabled(enable);
1952 - (void)_setAdditionalWebPlugInPaths:(NSArray *)newPaths
1954 if (!_private->pluginDatabase)
1955 _private->pluginDatabase = [[WebPluginDatabase alloc] init];
1957 [_private->pluginDatabase setPlugInPaths:newPaths];
1958 [_private->pluginDatabase refresh];
1961 - (void)_attachScriptDebuggerToAllFrames
1963 for (Frame* frame = core([self mainFrame]); frame; frame = frame->tree()->traverseNext())
1964 [kit(frame) _attachScriptDebugger];
1967 - (void)_detachScriptDebuggerFromAllFrames
1969 for (Frame* frame = core([self mainFrame]); frame; frame = frame->tree()->traverseNext())
1970 [kit(frame) _detachScriptDebugger];
1973 - (void)setBackgroundColor:(NSColor *)backgroundColor
1975 if ([_private->backgroundColor isEqual:backgroundColor])
1978 id old = _private->backgroundColor;
1979 _private->backgroundColor = [backgroundColor retain];
1982 [[self mainFrame] _updateBackgroundAndUpdatesWhileOffscreen];
1985 - (NSColor *)backgroundColor
1987 return _private->backgroundColor;
1990 - (BOOL)defersCallbacks
1992 if (!_private->page)
1994 return _private->page->defersLoading();
1997 - (void)setDefersCallbacks:(BOOL)defer
1999 if (!_private->page)
2001 return _private->page->setDefersLoading(defer);
2004 // For backwards compatibility with the WebBackForwardList API, we honor both
2005 // a per-WebView and a per-preferences setting for whether to use the page cache.
2007 - (BOOL)usesPageCache
2009 return _private->usesPageCache && [[self preferences] usesPageCache];
2012 - (void)setUsesPageCache:(BOOL)usesPageCache
2014 _private->usesPageCache = usesPageCache;
2016 // Post a notification so the WebCore settings update.
2017 [[self preferences] _postPreferencesChangesNotification];
2020 - (WebHistoryItem *)_globalHistoryItem
2022 if (!_private->page)
2024 return kit(_private->page->globalHistoryItem());
2027 - (WebTextIterator *)textIteratorForRect:(NSRect)rect
2029 IntPoint rectStart(rect.origin.x, rect.origin.y);
2030 IntPoint rectEnd(rect.origin.x + rect.size.width, rect.origin.y + rect.size.height);
2032 Frame* coreFrame = core([self mainFrame]);
2036 VisibleSelection selectionInsideRect(coreFrame->visiblePositionForPoint(rectStart), coreFrame->visiblePositionForPoint(rectEnd));
2038 return [[[WebTextIterator alloc] initWithRange:[DOMRange _wrapRange:selectionInsideRect.toNormalizedRange().get()]] autorelease];
2041 - (void)handleAuthenticationForResource:(id)identifier challenge:(NSURLAuthenticationChallenge *)challenge fromDataSource:(WebDataSource *)dataSource
2043 NSWindow *window = [self hostWindow] ? [self hostWindow] : [self window];
2044 [[WebPanelAuthenticationHandler sharedHandler] startAuthentication:challenge window:window];
2047 - (void)_clearUndoRedoOperations
2049 if (!_private->page)
2051 _private->page->clearUndoRedoOperations();
2054 - (void)_setCatchesDelegateExceptions:(BOOL)f
2056 _private->catchesDelegateExceptions = f;
2059 - (BOOL)_catchesDelegateExceptions
2061 return _private->catchesDelegateExceptions;
2064 - (void)_executeCoreCommandByName:(NSString *)name value:(NSString *)value
2066 Frame* coreFrame = core([self mainFrame]);
2069 coreFrame->editor()->command(name).execute(value);
2072 - (void)_setCustomHTMLTokenizerTimeDelay:(double)timeDelay
2074 if (!_private->page)
2076 return _private->page->setCustomHTMLTokenizerTimeDelay(timeDelay);
2079 - (void)_setCustomHTMLTokenizerChunkSize:(int)chunkSize
2081 if (!_private->page)
2083 return _private->page->setCustomHTMLTokenizerChunkSize(chunkSize);
2086 - (void)_clearMainFrameName
2088 _private->page->mainFrame()->tree()->clearName();
2091 - (void)setSelectTrailingWhitespaceEnabled:(BOOL)flag
2093 _private->selectTrailingWhitespaceEnabled = flag;
2095 [self setSmartInsertDeleteEnabled:false];
2098 - (BOOL)isSelectTrailingWhitespaceEnabled
2100 return _private->selectTrailingWhitespaceEnabled;
2103 - (void)setMemoryCacheDelegateCallsEnabled:(BOOL)enabled
2105 _private->page->setMemoryCacheClientCallsEnabled(enabled);
2108 - (BOOL)areMemoryCacheDelegateCallsEnabled
2110 return _private->page->areMemoryCacheClientCallsEnabled();
2113 - (void)_setJavaScriptURLsAreAllowed:(BOOL)areAllowed
2115 _private->page->setJavaScriptURLsAreAllowed(areAllowed);
2118 + (NSCursor *)_pointingHandCursor
2120 return handCursor().impl();
2123 #if USE(ACCELERATED_COMPOSITING)
2124 - (BOOL)_needsOneShotDrawingSynchronization
2126 return _private->needsOneShotDrawingSynchronization;
2129 - (void)_setNeedsOneShotDrawingSynchronization:(BOOL)needsSynchronization
2131 _private->needsOneShotDrawingSynchronization = needsSynchronization;
2134 - (void)_startedAcceleratedCompositingForFrame:(WebFrame*)webFrame
2136 BOOL entering = _private->acceleratedFramesCount == 0;
2138 [self willChangeValueForKey:UsingAcceleratedCompositingProperty];
2139 ++_private->acceleratedFramesCount;
2141 [self didChangeValueForKey:UsingAcceleratedCompositingProperty];
2144 - (void)_stoppedAcceleratedCompositingForFrame:(WebFrame*)webFrame
2146 BOOL leaving = _private->acceleratedFramesCount == 1;
2147 ASSERT(_private->acceleratedFramesCount > 0);
2150 [self willChangeValueForKey:UsingAcceleratedCompositingProperty];
2151 --_private->acceleratedFramesCount;
2153 [self didChangeValueForKey:UsingAcceleratedCompositingProperty];
2157 - (BOOL)_isUsingAcceleratedCompositing
2159 #if USE(ACCELERATED_COMPOSITING)
2160 return _private->acceleratedFramesCount > 0;
2168 @implementation _WebSafeForwarder
2170 // Used to send messages to delegates that implement informal protocols.
2172 - (id)initWithTarget:(id)t defaultTarget:(id)dt catchExceptions:(BOOL)c
2174 self = [super init];
2177 target = t; // Non retained.
2179 catchExceptions = c;
2183 - (void)forwardInvocation:(NSInvocation *)invocation
2185 if ([target respondsToSelector:[invocation selector]]) {
2186 if (catchExceptions) {
2188 [invocation invokeWithTarget:target];
2189 } @catch(id exception) {
2190 ReportDiscardedDelegateException([invocation selector], exception);
2193 [invocation invokeWithTarget:target];
2197 if ([defaultTarget respondsToSelector:[invocation selector]])
2198 [invocation invokeWithTarget:defaultTarget];
2200 // Do nothing quietly if method not implemented.
2203 - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
2205 return [defaultTarget methodSignatureForSelector:aSelector];
2210 @implementation WebView
2214 static BOOL initialized = NO;
2219 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_applicationWillTerminate) name:NSApplicationWillTerminateNotification object:NSApp];
2220 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:) name:WebPreferencesChangedNotification object:nil];
2221 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesRemovedNotification:) name:WebPreferencesRemovedNotification object:nil];
2224 + (void)_applicationWillTerminate
2226 applicationIsTerminating = YES;
2227 if (!pluginDatabaseClientCount)
2228 [WebPluginDatabase closeSharedDatabase];
2230 PageGroup::closeLocalStorage();
2233 + (BOOL)canShowMIMEType:(NSString *)MIMEType
2235 return [self _viewClass:nil andRepresentationClass:nil forMIMEType:MIMEType];
2238 - (WebBasePluginPackage *)_pluginForMIMEType:(NSString *)MIMEType
2240 WebBasePluginPackage *pluginPackage = [[WebPluginDatabase sharedDatabase] pluginForMIMEType:MIMEType];
2242 return pluginPackage;
2244 if (_private->pluginDatabase)
2245 return [_private->pluginDatabase pluginForMIMEType:MIMEType];
2250 - (WebBasePluginPackage *)_pluginForExtension:(NSString *)extension
2252 WebBasePluginPackage *pluginPackage = [[WebPluginDatabase sharedDatabase] pluginForExtension:extension];
2254 return pluginPackage;
2256 if (_private->pluginDatabase)
2257 return [_private->pluginDatabase pluginForExtension:extension];
2262 - (void)addPluginInstanceView:(NSView *)view
2264 if (!_private->pluginDatabase)
2265 _private->pluginDatabase = [[WebPluginDatabase alloc] init];
2266 [_private->pluginDatabase addPluginInstanceView:view];
2269 - (void)removePluginInstanceView:(NSView *)view
2271 if (_private->pluginDatabase)
2272 [_private->pluginDatabase removePluginInstanceView:view];
2275 - (void)removePluginInstanceViewsFor:(WebFrame*)webFrame
2277 if (_private->pluginDatabase)
2278 [_private->pluginDatabase removePluginInstanceViewsFor:webFrame];
2281 - (BOOL)_isMIMETypeRegisteredAsPlugin:(NSString *)MIMEType
2283 if ([[WebPluginDatabase sharedDatabase] isMIMETypeRegistered:MIMEType])
2286 if (_private->pluginDatabase && [_private->pluginDatabase isMIMETypeRegistered:MIMEType])
2292 + (BOOL)canShowMIMETypeAsHTML:(NSString *)MIMEType
2294 return [WebFrameView _canShowMIMETypeAsHTML:MIMEType];
2297 + (NSArray *)MIMETypesShownAsHTML
2299 NSMutableDictionary *viewTypes = [WebFrameView _viewTypesAllowImageTypeOmission:YES];
2300 NSEnumerator *enumerator = [viewTypes keyEnumerator];
2302 NSMutableArray *array = [[[NSMutableArray alloc] init] autorelease];
2304 while ((key = [enumerator nextObject])) {
2305 if ([viewTypes objectForKey:key] == [WebHTMLView class])
2306 [array addObject:key];
2312 + (void)setMIMETypesShownAsHTML:(NSArray *)MIMETypes
2314 NSDictionary *viewTypes = [[WebFrameView _viewTypesAllowImageTypeOmission:YES] copy];
2315 NSEnumerator *enumerator = [viewTypes keyEnumerator];
2317 while ((key = [enumerator nextObject])) {
2318 if ([viewTypes objectForKey:key] == [WebHTMLView class])
2319 [WebView _unregisterViewClassAndRepresentationClassForMIMEType:key];
2322 int i, count = [MIMETypes count];
2323 for (i = 0; i < count; i++) {
2324 [WebView registerViewClass:[WebHTMLView class]
2325 representationClass:[WebHTMLRepresentation class]
2326 forMIMEType:[MIMETypes objectAtIndex:i]];
2328 [viewTypes release];
2331 + (NSURL *)URLFromPasteboard:(NSPasteboard *)pasteboard
2333 return [pasteboard _web_bestURL];
2336 + (NSString *)URLTitleFromPasteboard:(NSPasteboard *)pasteboard
2338 return [pasteboard stringForType:WebURLNamePboardType];
2341 + (void)registerURLSchemeAsLocal:(NSString *)protocol
2343 FrameLoader::registerURLSchemeAsLocal(protocol);
2346 - (id)_initWithArguments:(NSDictionary *) arguments
2348 NSCoder *decoder = [arguments objectForKey:@"decoder"];
2350 self = [self initWithCoder:decoder];
2352 ASSERT([arguments objectForKey:@"frame"]);
2353 NSValue *frameValue = [arguments objectForKey:@"frame"];
2354 NSRect frame = (frameValue ? [frameValue rectValue] : NSZeroRect);
2355 NSString *frameName = [arguments objectForKey:@"frameName"];
2356 NSString *groupName = [arguments objectForKey:@"groupName"];
2357 self = [self initWithFrame:frame frameName:frameName groupName:groupName];
2363 static bool needsWebViewInitThreadWorkaround()
2365 static BOOL isOldClient = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_WEBVIEW_INIT_THREAD_WORKAROUND)
2366 && ([[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.installer"] ||
2367 [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.Automator"]);
2368 return isOldClient && !pthread_main_np();
2371 - (id)initWithFrame:(NSRect)f
2373 return [self initWithFrame:f frameName:nil groupName:nil];
2376 - (id)initWithFrame:(NSRect)f frameName:(NSString *)frameName groupName:(NSString *)groupName
2378 if (needsWebViewInitThreadWorkaround())
2379 return [[self _webkit_invokeOnMainThread] initWithFrame:f frameName:frameName groupName:groupName];
2381 WebCoreThreadViolationCheck();
2382 return [self _initWithFrame:f frameName:frameName groupName:groupName usesDocumentViews:YES];
2385 - (id)initWithCoder:(NSCoder *)decoder
2387 if (needsWebViewInitThreadWorkaround())
2388 return [[self _webkit_invokeOnMainThread] initWithCoder:decoder];
2390 WebCoreThreadViolationCheck();
2391 WebView *result = nil;
2394 NSString *frameName;
2395 NSString *groupName;
2396 WebPreferences *preferences;
2397 BOOL useBackForwardList = NO;
2398 BOOL allowsUndo = YES;
2400 result = [super initWithCoder:decoder];
2401 result->_private = [[WebViewPrivate alloc] init];
2403 // We don't want any of the archived subviews. The subviews will always
2404 // be created in _commonInitializationFrameName:groupName:.
2405 [[result subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
2407 if ([decoder allowsKeyedCoding]) {
2408 frameName = [decoder decodeObjectForKey:@"FrameName"];
2409 groupName = [decoder decodeObjectForKey:@"GroupName"];
2410 preferences = [decoder decodeObjectForKey:@"Preferences"];
2411 useBackForwardList = [decoder decodeBoolForKey:@"UseBackForwardList"];
2412 if ([decoder containsValueForKey:@"AllowsUndo"])
2413 allowsUndo = [decoder decodeBoolForKey:@"AllowsUndo"];
2416 [decoder decodeValueOfObjCType:@encode(int) at:&version];
2417 frameName = [decoder decodeObject];
2418 groupName = [decoder decodeObject];
2419 preferences = [decoder decodeObject];
2421 [decoder decodeValuesOfObjCTypes:"c", &useBackForwardList];
2422 // The allowsUndo field is no longer written out in encodeWithCoder, but since there are
2423 // version 3 NIBs that have this field encoded, we still need to read it in.
2425 [decoder decodeValuesOfObjCTypes:"c", &allowsUndo];
2428 if (![frameName isKindOfClass:[NSString class]])
2430 if (![groupName isKindOfClass:[NSString class]])
2432 if (![preferences isKindOfClass:[WebPreferences class]])
2435 LOG(Encoding, "FrameName = %@, GroupName = %@, useBackForwardList = %d\n", frameName, groupName, (int)useBackForwardList);
2436 [result _commonInitializationWithFrameName:frameName groupName:groupName usesDocumentViews:YES];
2437 [result page]->backForwardList()->setEnabled(useBackForwardList);
2438 result->_private->allowsUndo = allowsUndo;
2440 [result setPreferences:preferences];
2441 } @catch (NSException *localException) {
2449 - (void)encodeWithCoder:(NSCoder *)encoder
2451 // Set asside the subviews before we archive. We don't want to archive any subviews.
2452 // The subviews will always be created in _commonInitializationFrameName:groupName:.
2453 id originalSubviews = _subviews;
2456 [super encodeWithCoder:encoder];
2458 // Restore the subviews we set aside.
2459 _subviews = originalSubviews;
2461 BOOL useBackForwardList = _private->page && _private->page->backForwardList()->enabled();
2462 if ([encoder allowsKeyedCoding]) {
2463 [encoder encodeObject:[[self mainFrame] name] forKey:@"FrameName"];
2464 [encoder encodeObject:[self groupName] forKey:@"GroupName"];
2465 [encoder encodeObject:[self preferences] forKey:@"Preferences"];
2466 [encoder encodeBool:useBackForwardList forKey:@"UseBackForwardList"];
2467 [encoder encodeBool:_private->allowsUndo forKey:@"AllowsUndo"];
2469 int version = WebViewVersion;
2470 [encoder encodeValueOfObjCType:@encode(int) at:&version];
2471 [encoder encodeObject:[[self mainFrame] name]];
2472 [encoder encodeObject:[self groupName]];
2473 [encoder encodeObject:[self preferences]];
2474 [encoder encodeValuesOfObjCTypes:"c", &useBackForwardList];
2475 // DO NOT encode any new fields here, doing so will break older WebKit releases.
2478 LOG(Encoding, "FrameName = %@, GroupName = %@, useBackForwardList = %d\n", [[self mainFrame] name], [self groupName], (int)useBackForwardList);
2483 if (WebCoreObjCScheduleDeallocateOnMainThread([WebView class], self))
2486 // call close to ensure we tear-down completely
2487 // this maintains our old behavior for existing applications
2493 // [super dealloc] can end up dispatching against _private (3466082)
2501 ASSERT(_private->closed);
2510 // _close existed first, and some clients might be calling or overriding it, so call through.
2514 - (void)setShouldCloseWithWindow:(BOOL)close
2516 _private->shouldCloseWithWindow = close;
2519 - (BOOL)shouldCloseWithWindow
2521 return _private->shouldCloseWithWindow;
2524 - (void)removeSizeObservers
2526 if (!_private->useDocumentViews && [self window]) {
2527 [[NSNotificationCenter defaultCenter] removeObserver:self
2528 name:NSViewFrameDidChangeNotification object:self];
2529 [[NSNotificationCenter defaultCenter] removeObserver:self
2530 name:NSViewBoundsDidChangeNotification object:self];
2534 - (void)addSizeObservers
2536 if (!_private->useDocumentViews && [self window]) {
2537 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_boundsChanged)
2538 name:NSViewFrameDidChangeNotification object:self];
2539 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_boundsChanged)
2540 name:NSViewBoundsDidChangeNotification object:self];
2541 [self _boundsChanged];
2545 - (void)addWindowObservers
2547 NSWindow *window = [self window];
2548 if (!_private->useDocumentViews && window) {
2549 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowDidBecomeKey:)
2550 name:NSWindowDidBecomeKeyNotification object:nil];
2551 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowDidResignKey:)
2552 name:NSWindowDidResignKeyNotification object:nil];
2553 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillOrderOnScreen:)
2554 name:WKWindowWillOrderOnScreenNotification() object:window];
2558 - (void)removeWindowObservers
2560 NSWindow *window = [self window];
2561 if (!_private->useDocumentViews && window) {
2562 [[NSNotificationCenter defaultCenter] removeObserver:self
2563 name:NSWindowDidBecomeKeyNotification object:nil];
2564 [[NSNotificationCenter defaultCenter] removeObserver:self
2565 name:NSWindowDidResignKeyNotification object:nil];
2566 [[NSNotificationCenter defaultCenter] removeObserver:self
2567 name:WKWindowWillOrderOnScreenNotification() object:window];
2571 - (void)viewWillMoveToWindow:(NSWindow *)window
2573 // Don't do anything if the WebView isn't initialized.
2574 // This happens when decoding a WebView in a nib.
2575 // FIXME: What sets up the observer of NSWindowWillCloseNotification in this case?
2579 if (_private->closed)
2582 if ([self window] && [self window] != [self hostWindow])
2583 [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowWillCloseNotification object:[self window]];
2586 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillClose:) name:NSWindowWillCloseNotification object:window];
2588 // Ensure that we will receive the events that WebHTMLView (at least) needs.
2589 // The following are expensive enough that we don't want to call them over
2590 // and over, so do them when we move into a window.
2591 [window setAcceptsMouseMovedEvents:YES];
2592 WKSetNSWindowShouldPostEventNotifications(window, YES);
2594 [self removeWindowObservers];
2595 [self removeSizeObservers];
2597 _private->page->willMoveOffscreen();
2600 - (void)viewDidMoveToWindow
2602 // Don't do anything if we aren't initialized. This happens
2603 // when decoding a WebView. When WebViews are decoded their subviews
2604 // are created by initWithCoder: and so won't be normally
2605 // initialized. The stub views are discarded by WebView.
2606 if (!_private || _private->closed)
2609 if ([self window]) {
2610 [self addWindowObservers];
2611 [self addSizeObservers];
2612 _private->page->didMoveOnscreen();
2616 - (void)_updateFocusedAndActiveState
2618 ASSERT(!_private->useDocumentViews);
2619 [self _updateFocusedAndActiveStateForFrame:[self mainFrame]];
2622 - (void)_updateFocusedAndActiveStateForFrame:(WebFrame *)webFrame
2624 Frame* frame = core(webFrame);
2628 Page* page = frame->page();
2632 NSWindow *window = [self window];
2633 BOOL windowIsKey = [window isKeyWindow];
2634 BOOL windowOrSheetIsKey = windowIsKey || [[window attachedSheet] isKeyWindow];
2636 WebFrameView *mainFrameView = [[self mainFrame] frameView];
2637 id <WebDocumentView> documentView = [mainFrameView documentView];
2638 BOOL documentViewIsResigningFirstResponder = [documentView isKindOfClass:[WebHTMLView class]] && [(WebHTMLView *)documentView _isResigningFirstResponder];
2640 NSResponder *firstResponder = [window firstResponder];
2641 if ([firstResponder isKindOfClass:[NSView class]]
2642 && [(NSView *)firstResponder isDescendantOf:mainFrameView])
2643 page->focusController()->setActive(windowIsKey && !documentViewIsResigningFirstResponder);
2645 Frame* focusedFrame = page->focusController()->focusedOrMainFrame();
2646 frame->selection()->setFocused(frame == focusedFrame && windowOrSheetIsKey);
2649 - (void)_windowDidBecomeKey:(NSNotification *)notification
2651 ASSERT(!_private->useDocumentViews);
2652 NSWindow *keyWindow = [notification object];
2653 if (keyWindow == [self window] || keyWindow == [[self window] attachedSheet])
2654 [self _updateFocusedAndActiveState];
2657 - (void)_windowDidResignKey:(NSNotification *)notification
2659 ASSERT(!_private->useDocumentViews);
2660 NSWindow *formerKeyWindow = [notification object];
2661 if (formerKeyWindow == [self window] || formerKeyWindow == [[self window] attachedSheet])
2662 [self _updateFocusedAndActiveState];
2665 - (void)_windowWillOrderOnScreen:(NSNotification *)notification
2667 ASSERT(!_private->useDocumentViews);
2668 if (![self shouldUpdateWhileOffscreen])
2669 [self setNeedsDisplay:YES];
2672 - (void)_windowWillClose:(NSNotification *)notification
2674 if ([self shouldCloseWithWindow] && ([self window] == [self hostWindow] || ([self window] && ![self hostWindow]) || (![self window] && [self hostWindow])))
2678 - (void)setPreferences:(WebPreferences *)prefs
2681 prefs = [WebPreferences standardPreferences];
2683 if (_private->preferences == prefs)
2686 [prefs willAddToWebView];
2688 WebPreferences *oldPrefs = _private->preferences;
2690 [[NSNotificationCenter defaultCenter] removeObserver:self name:WebPreferencesChangedNotification object:[self preferences]];
2691 [WebPreferences _removeReferenceForIdentifier:[oldPrefs identifier]];
2693 _private->preferences = [prefs retain];
2695 // After registering for the notification, post it so the WebCore settings update.
2696 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:)
2697 name:WebPreferencesChangedNotification object:[self preferences]];
2698 [[self preferences] _postPreferencesChangesNotification];
2700 [oldPrefs didRemoveFromWebView];
2704 - (WebPreferences *)preferences
2706 return _private->preferences;
2709 - (void)setPreferencesIdentifier:(NSString *)anIdentifier
2711 if (!_private->closed && ![anIdentifier isEqual:[[self preferences] identifier]]) {
2712 WebPreferences *prefs = [[WebPreferences alloc] initWithIdentifier:anIdentifier];
2713 [self setPreferences:prefs];
2718 - (NSString *)preferencesIdentifier
2720 return [[self preferences] identifier];
2724 - (void)setUIDelegate:delegate
2726 _private->UIDelegate = delegate;
2727 [_private->UIDelegateForwarder release];
2728 _private->UIDelegateForwarder = nil;
2733 return _private->UIDelegate;
2736 - (void)setResourceLoadDelegate: delegate
2738 _private->resourceProgressDelegate = delegate;
2739 [self _cacheResourceLoadDelegateImplementations];
2742 - resourceLoadDelegate
2744 return _private->resourceProgressDelegate;
2747 - (void)setDownloadDelegate: delegate
2749 _private->downloadDelegate = delegate;
2755 return _private->downloadDelegate;
2758 - (void)setPolicyDelegate:delegate
2760 _private->policyDelegate = delegate;
2761 [_private->policyDelegateForwarder release];
2762 _private->policyDelegateForwarder = nil;
2767 return _private->policyDelegate;
2770 - (void)setFrameLoadDelegate:delegate
2772 _private->frameLoadDelegate = delegate;
2773 [self _cacheFrameLoadDelegateImplementations];
2775 // If this delegate wants callbacks for icons, fire up the icon database.
2776 if (_private->frameLoadDelegateImplementations.didReceiveIconForFrameFunc)
2777 [WebIconDatabase sharedIconDatabase];
2782 return _private->frameLoadDelegate;
2785 - (WebFrame *)mainFrame
2787 // This can be called in initialization, before _private has been set up (3465613)
2790 if (!_private->page)
2792 return kit(_private->page->mainFrame());
2795 - (WebFrame *)selectedFrame
2797 // If the first responder is a view in our tree, we get the frame containing the first responder.
2798 // This is faster than searching the frame hierarchy, and will give us a result even in the case
2799 // where the focused frame doesn't actually contain a selection.
2800 WebFrame *focusedFrame = [self _focusedFrame];
2802 return focusedFrame;
2804 // If the first responder is outside of our view tree, we search for a frame containing a selection.
2805 // There should be at most only one of these.
2806 return [[self mainFrame] _findFrameWithSelection];
2809 - (WebBackForwardList *)backForwardList
2811 if (!_private->page)
2813 if (!_private->page->backForwardList()->enabled())
2815 return kit(_private->page->backForwardList());
2818 - (void)setMaintainsBackForwardList: (BOOL)flag
2820 if (!_private->page)
2822 _private->page->backForwardList()->setEnabled(flag);
2827 if (!_private->page)
2830 return _private->page->goBack();
2835 if (!_private->page)
2838 return _private->page->goForward();
2841 - (BOOL)goToBackForwardItem:(WebHistoryItem *)item
2843 if (!_private->page)
2846 _private->page->goToItem(core(item), FrameLoadTypeIndexedBackForward);
2850 - (void)setTextSizeMultiplier:(float)m
2852 [self _setZoomMultiplier:m isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
2855 - (float)textSizeMultiplier
2857 return [self _realZoomMultiplierIsTextOnly] ? _private->zoomMultiplier : 1.0f;
2860 - (void)_setZoomMultiplier:(float)m isTextOnly:(BOOL)isTextOnly
2862 // NOTE: This has no visible effect when viewing a PDF (see <rdar://problem/4737380>)
2863 _private->zoomMultiplier = m;
2864 ASSERT(_private->page);
2866 _private->page->settings()->setZoomsTextOnly(isTextOnly);
2868 // FIXME: it would be nice to rework this code so that _private->zoomMultiplier doesn't exist and callers
2869 // all access _private->page->settings().
2870 Frame* coreFrame = core([self mainFrame]);
2872 coreFrame->setZoomFactor(m, isTextOnly);
2875 - (float)_zoomMultiplier:(BOOL)isTextOnly
2877 if (isTextOnly != [self _realZoomMultiplierIsTextOnly])
2879 return _private->zoomMultiplier;
2882 - (float)_realZoomMultiplier
2884 return _private->zoomMultiplier;
2887 - (BOOL)_realZoomMultiplierIsTextOnly
2889 if (!_private->page)
2892 return _private->page->settings()->zoomsTextOnly();
2895 #define MinimumZoomMultiplier 0.5f
2896 #define MaximumZoomMultiplier 3.0f
2897 #define ZoomMultiplierRatio 1.2f
2899 - (BOOL)_canZoomOut:(BOOL)isTextOnly
2901 id docView = [[[self mainFrame] frameView] documentView];
2902 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
2903 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
2904 return [zoomingDocView _canZoomOut];
2906 return [self _zoomMultiplier:isTextOnly] / ZoomMultiplierRatio > MinimumZoomMultiplier;
2910 - (BOOL)_canZoomIn:(BOOL)isTextOnly
2912 id docView = [[[self mainFrame] frameView] documentView];
2913 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
2914 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
2915 return [zoomingDocView _canZoomIn];
2917 return [self _zoomMultiplier:isTextOnly] * ZoomMultiplierRatio < MaximumZoomMultiplier;
2920 - (IBAction)_zoomOut:(id)sender isTextOnly:(BOOL)isTextOnly
2922 id docView = [[[self mainFrame] frameView] documentView];
2923 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
2924 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
2925 return [zoomingDocView _zoomOut:sender];
2927 float newScale = [self _zoomMultiplier:isTextOnly] / ZoomMultiplierRatio;
2928 if (newScale > MinimumZoomMultiplier)
2929 [self _setZoomMultiplier:newScale isTextOnly:isTextOnly];
2932 - (IBAction)_zoomIn:(id)sender isTextOnly:(BOOL)isTextOnly
2934 id docView = [[[self mainFrame] frameView] documentView];
2935 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
2936 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
2937 return [zoomingDocView _zoomIn:sender];
2939 float newScale = [self _zoomMultiplier:isTextOnly] * ZoomMultiplierRatio;
2940 if (newScale < MaximumZoomMultiplier)
2941 [self _setZoomMultiplier:newScale isTextOnly:isTextOnly];
2944 - (BOOL)_canResetZoom:(BOOL)isTextOnly
2946 id docView = [[[self mainFrame] frameView] documentView];
2947 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
2948 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
2949 return [zoomingDocView _canResetZoom];
2951 return [self _zoomMultiplier:isTextOnly] != 1.0f;
2954 - (IBAction)_resetZoom:(id)sender isTextOnly:(BOOL)isTextOnly
2956 id docView = [[[self mainFrame] frameView] documentView];
2957 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
2958 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
2959 return [zoomingDocView _resetZoom:sender];
2961 if ([self _zoomMultiplier:isTextOnly] != 1.0f)
2962 [self _setZoomMultiplier:1.0f isTextOnly:isTextOnly];
2965 - (void)viewWillMoveToSuperview:(NSView *)newSuperview
2967 [self removeSizeObservers];
2970 - (void)viewDidMoveToSuperview
2972 if ([self superview] != nil)
2973 [self addSizeObservers];
2976 - (void)setApplicationNameForUserAgent:(NSString *)applicationName
2978 NSString *name = [applicationName copy];
2979 [_private->applicationNameForUserAgent release];
2980 _private->applicationNameForUserAgent = name;
2981 if (!_private->userAgentOverridden)
2982 _private->userAgent = String();
2985 - (NSString *)applicationNameForUserAgent
2987 return [[_private->applicationNameForUserAgent retain] autorelease];
2990 - (void)setCustomUserAgent:(NSString *)userAgentString
2992 _private->userAgent = userAgentString;
2993 _private->userAgentOverridden = userAgentString != nil;
2996 - (NSString *)customUserAgent
2998 if (!_private->userAgentOverridden)
3000 return _private->userAgent;
3003 - (void)setMediaStyle:(NSString *)mediaStyle
3005 if (_private->mediaStyle != mediaStyle) {
3006 [_private->mediaStyle release];
3007 _private->mediaStyle = [mediaStyle copy];
3011 - (NSString *)mediaStyle
3013 return _private->mediaStyle;
3016 - (BOOL)supportsTextEncoding
3018 id documentView = [[[self mainFrame] frameView] documentView];
3019 return [documentView conformsToProtocol:@protocol(WebDocumentText)]
3020 && [documentView supportsTextEncoding];
3023 - (void)setCustomTextEncodingName:(NSString *)encoding
3025 NSString *oldEncoding = [self customTextEncodingName];
3026 if (encoding == oldEncoding || [encoding isEqualToString:oldEncoding])
3028 if (Frame* mainFrame = core([self mainFrame]))
3029 mainFrame->loader()->reloadWithOverrideEncoding(encoding);
3032 - (NSString *)_mainFrameOverrideEncoding
3034 WebDataSource *dataSource = [[self mainFrame] provisionalDataSource];
3035 if (dataSource == nil)
3036 dataSource = [[self mainFrame] _dataSource];
3037 if (dataSource == nil)
3039 return nsStringNilIfEmpty([dataSource _documentLoader]->overrideEncoding());
3042 - (NSString *)customTextEncodingName
3044 return [self _mainFrameOverrideEncoding];
3047 - (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script
3049 // Return statements are only valid in a function but some applications pass in scripts
3050 // prefixed with return (<rdar://problems/5103720&4616860>) since older WebKit versions
3051 // silently ignored the return. If the application is linked against an earlier version
3052 // of WebKit we will strip the return so the script wont fail.
3053 if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_JAVASCRIPT_RETURN_QUIRK)) {
3054 NSRange returnStringRange = [script rangeOfString:@"return "];
3055 if (returnStringRange.length && !returnStringRange.location)
3056 script = [script substringFromIndex:returnStringRange.location + returnStringRange.length];
3059 NSString *result = [[self mainFrame] _stringByEvaluatingJavaScriptFromString:script];
3060 // The only way stringByEvaluatingJavaScriptFromString can return nil is if the frame was removed by the script
3061 // Since there's no way to get rid of the main frame, result will never ever be nil here.
3067 - (WebScriptObject *)windowScriptObject
3069 Frame* coreFrame = core([self mainFrame]);
3072 return coreFrame->script()->windowScriptObject();
3075 // Get the appropriate user-agent string for a particular URL.
3076 - (NSString *)userAgentForURL:(NSURL *)url
3078 return [self _userAgentForURL:KURL([url absoluteURL])];
3081 - (void)setHostWindow:(NSWindow *)hostWindow
3083 if (_private->closed)
3085 if (hostWindow == _private->hostWindow)
3088 Frame* coreFrame = core([self mainFrame]);
3089 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
3090 [[[kit(frame) frameView] documentView] viewWillMoveToHostWindow:hostWindow];
3091 if (_private->hostWindow && [self window] != _private->hostWindow)
3092 [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowWillCloseNotification object:_private->hostWindow];
3094 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillClose:) name:NSWindowWillCloseNotification object:hostWindow];
3095 [_private->hostWindow release];
3096 _private->hostWindow = [hostWindow retain];
3097 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
3098 [[[kit(frame) frameView] documentView] viewDidMoveToHostWindow];
3101 - (NSWindow *)hostWindow
3103 // -[WebView hostWindow] can sometimes be called from the WebView's [super dealloc] method
3104 // so we check here to make sure it's not null.
3108 return _private->hostWindow;
3111 - (NSView <WebDocumentView> *)documentViewAtWindowPoint:(NSPoint)point
3113 return [[self _frameViewAtWindowPoint:point] documentView];
3116 - (NSDictionary *)_elementAtWindowPoint:(NSPoint)windowPoint
3118 WebFrameView *frameView = [self _frameViewAtWindowPoint:windowPoint];
3121 NSView <WebDocumentView> *documentView = [frameView documentView];
3122 if ([documentView conformsToProtocol:@protocol(WebDocumentElement)]) {
3123 NSPoint point = [documentView convertPoint:windowPoint fromView:nil];
3124 return [(NSView <WebDocumentElement> *)documentView elementAtPoint:point];
3126 return [NSDictionary dictionaryWithObject:[frameView webFrame] forKey:WebElementFrameKey];
3129 - (NSDictionary *)elementAtPoint:(NSPoint)point
3131 return [self _elementAtWindowPoint:[self convertPoint:point toView:nil]];
3134 // The following 2 internal NSView methods are called on the drag destination by make scrolling while dragging work.
3135 // Scrolling while dragging will only work if the drag destination is in a scroll view. The WebView is the drag destination.
3136 // When dragging to a WebView, the document subview should scroll, but it doesn't because it is not the drag destination.
3137 // Forward these calls to the document subview to make its scroll view scroll.
3138 - (void)_autoscrollForDraggingInfo:(id)draggingInfo timeDelta:(NSTimeInterval)repeatDelta
3140 NSView <WebDocumentView> *documentView = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3141 [documentView _autoscrollForDraggingInfo:draggingInfo timeDelta:repeatDelta];
3144 - (BOOL)_shouldAutoscrollForDraggingInfo:(id)draggingInfo
3146 NSView <WebDocumentView> *documentView = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3147 return [documentView _shouldAutoscrollForDraggingInfo:draggingInfo];
3150 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)draggingInfo
3152 NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3153 WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]] ? (WebHTMLView*)view : nil);
3154 IntPoint client([draggingInfo draggingLocation]);
3155 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
3156 DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
3157 return core(self)->dragController()->dragEntered(&dragData);
3160 - (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)draggingInfo
3162 Page* page = core(self);
3164 return NSDragOperationNone;
3166 NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3167 WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]] ? (WebHTMLView*)view : nil);
3168 IntPoint client([draggingInfo draggingLocation]);
3169 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
3170 DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
3171 return page->dragController()->dragUpdated(&dragData);
3174 - (void)draggingExited:(id <NSDraggingInfo>)draggingInfo
3176 Page* page = core(self);
3180 NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3181 WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]] ? (WebHTMLView*)view : nil);
3182 IntPoint client([draggingInfo draggingLocation]);
3183 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
3184 DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
3185 page->dragController()->dragExited(&dragData);
3188 - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)draggingInfo
3193 - (BOOL)performDragOperation:(id <NSDraggingInfo>)draggingInfo
3195 NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3196 WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]]? (WebHTMLView*)view : nil);
3197 IntPoint client([draggingInfo draggingLocation]);
3198 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
3199 DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
3200 return core(self)->dragController()->performDrag(&dragData);
3203 - (NSView *)_hitTest:(NSPoint *)aPoint dragTypes:(NSSet *)types
3205 NSView *hitView = [super _hitTest:aPoint dragTypes:types];
3206 if (!hitView && [[self superview] mouse:*aPoint inRect:[self frame]]) {
3213 - (BOOL)acceptsFirstResponder
3215 return [[[self mainFrame] frameView] acceptsFirstResponder];
3218 - (BOOL)becomeFirstResponder
3220 if (_private->becomingFirstResponder) {
3221 // Fix for unrepro infinite recursion reported in radar 4448181. If we hit this assert on
3222 // a debug build, we should figure out what causes the problem and do a better fix.
3223 ASSERT_NOT_REACHED();
3227 // This works together with setNextKeyView to splice the WebView into
3228 // the key loop similar to the way NSScrollView does this. Note that
3229 // WebFrameView has very similar code.
3230 NSWindow *window = [self window];
3231 WebFrameView *mainFrameView = [[self mainFrame] frameView];
3233 NSResponder *previousFirstResponder = [[self window] _oldFirstResponderBeforeBecoming];
3234 BOOL fromOutside = ![previousFirstResponder isKindOfClass:[NSView class]] || (![(NSView *)previousFirstResponder isDescendantOf:self] && previousFirstResponder != self);
3236 if ([window keyViewSelectionDirection] == NSSelectingPrevious) {
3237 NSView *previousValidKeyView = [self previousValidKeyView];
3238 if ((previousValidKeyView != self) && (previousValidKeyView != mainFrameView)) {
3239 _private->becomingFirstResponder = YES;
3240 _private->becomingFirstResponderFromOutside = fromOutside;
3241 [window makeFirstResponder:previousValidKeyView];
3242 _private->becomingFirstResponderFromOutside = NO;
3243 _private->becomingFirstResponder = NO;
3250 if ([mainFrameView acceptsFirstResponder]) {
3251 _private->becomingFirstResponder = YES;
3252 _private->becomingFirstResponderFromOutside = fromOutside;
3253 [window makeFirstResponder:mainFrameView];
3254 _private->becomingFirstResponderFromOutside = NO;
3255 _private->becomingFirstResponder = NO;
3262 - (NSView *)_webcore_effectiveFirstResponder
3264 WebFrameView *frameView = [[self mainFrame] frameView];
3265 return frameView ? [frameView _webcore_effectiveFirstResponder] : [super _webcore_effectiveFirstResponder];
3268 - (void)setNextKeyView:(NSView *)aView
3270 // This works together with becomeFirstResponder to splice the WebView into
3271 // the key loop similar to the way NSScrollView does this. Note that
3272 // WebFrameView has very similar code.
3273 WebFrameView *mainFrameView = [[self mainFrame] frameView];
3274 if (mainFrameView != nil) {
3275 [mainFrameView setNextKeyView:aView];
3277 [super setNextKeyView:aView];
3281 static WebFrame *incrementFrame(WebFrame *curr, BOOL forward, BOOL wrapFlag)
3283 Frame* coreFrame = core(curr);
3285 ? coreFrame->tree()->traverseNextWithWrap(wrapFlag)
3286 : coreFrame->tree()->traversePreviousWithWrap(wrapFlag));
3289 - (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag
3291 return [self searchFor:string direction:forward caseSensitive:caseFlag wrap:wrapFlag startInSelection:NO];
3294 + (void)registerViewClass:(Class)viewClass representationClass:(Class)representationClass forMIMEType:(NSString *)MIMEType
3296 [[WebFrameView _viewTypesAllowImageTypeOmission:YES] setObject:viewClass forKey:MIMEType];
3297 [[WebDataSource _repTypesAllowImageTypeOmission:YES] setObject:representationClass forKey:MIMEType];
3299 // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
3300 // in the WebCore MIMEType registry. For now we're doing this in a safe, limited manner
3301 // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
3302 if ([viewClass class] == [WebHTMLView class])
3303 MIMETypeRegistry::getSupportedNonImageMIMETypes().add(MIMEType);
3306 - (void)setGroupName:(NSString *)groupName
3308 if (!_private->page)
3310 _private->page->setGroupName(groupName);
3313 - (NSString *)groupName
3315 if (!_private->page)
3317 return _private->page->groupName();
3320 - (double)estimatedProgress
3322 if (!_private->page)
3325 return _private->page->progress()->estimatedProgress();
3328 - (NSArray *)pasteboardTypesForSelection
3330 NSView <WebDocumentView> *documentView = [[[self _selectedOrMainFrame] frameView] documentView];
3331 if ([documentView conformsToProtocol:@protocol(WebDocumentSelection)]) {
3332 return [(NSView <WebDocumentSelection> *)documentView pasteboardTypesForSelection];
3334 return [NSArray array];
3337 - (void)writeSelectionWithPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
3339 WebFrame *frame = [self _selectedOrMainFrame];
3340 if (frame && [frame _hasSelection]) {
3341 NSView <WebDocumentView> *documentView = [[frame frameView] documentView];
3342 if ([documentView conformsToProtocol:@protocol(WebDocumentSelection)])
3343 [(NSView <WebDocumentSelection> *)documentView writeSelectionWithPasteboardTypes:types toPasteboard:pasteboard];
3347 - (NSArray *)pasteboardTypesForElement:(NSDictionary *)element
3349 if ([element objectForKey:WebElementImageURLKey] != nil) {
3350 return [NSPasteboard _web_writableTypesForImageIncludingArchive:([element objectForKey:WebElementDOMNodeKey] != nil)];
3351 } else if ([element objectForKey:WebElementLinkURLKey] != nil) {
3352 return [NSPasteboard _web_writableTypesForURL];
3353 } else if ([[element objectForKey:WebElementIsSelectedKey] boolValue]) {
3354 return [self pasteboardTypesForSelection];
3356 return [NSArray array];
3359 - (void)writeElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
3361 if ([element objectForKey:WebElementImageURLKey] != nil) {
3362 [self _writeImageForElement:element withPasteboardTypes:types toPasteboard:pasteboard];
3363 } else if ([element objectForKey:WebElementLinkURLKey] != nil) {
3364 [self _writeLinkElement:element withPasteboardTypes:types toPasteboard:pasteboard];
3365 } else if ([[element objectForKey:WebElementIsSelectedKey] boolValue]) {
3366 [self writeSelectionWithPasteboardTypes:types toPasteboard:pasteboard];
3370 - (void)moveDragCaretToPoint:(NSPoint)point
3372 if (Page* page = core(self))
3373 page->dragController()->placeDragCaret(IntPoint([self convertPoint:point toView:nil]));
3376 - (void)removeDragCaret
3378 if (Page* page = core(self))
3379 page->dragController()->dragEnded();
3382 - (void)setMainFrameURL:(NSString *)URLString
3384 [[self mainFrame] loadRequest: [NSURLRequest requestWithURL: [NSURL _web_URLWithDataAsString: URLString]]];
3387 - (NSString *)mainFrameURL
3390 ds = [[self mainFrame] provisionalDataSource];
3392 ds = [[self mainFrame] _dataSource];
3393 return [[[ds request] URL] _web_originalDataAsString];
3398 LOG (Bindings, "isLoading = %d", (int)[self _isLoading]);
3399 return [self _isLoading];
3402 - (NSString *)mainFrameTitle
3404 NSString *mainFrameTitle = [[[self mainFrame] _dataSource] pageTitle];
3405 return (mainFrameTitle != nil) ? mainFrameTitle : (NSString *)@"";
3408 - (NSImage *)mainFrameIcon
3410 return [[WebIconDatabase sharedIconDatabase] iconForURL:[[[[self mainFrame] _dataSource] _URL] _web_originalDataAsString] withSize:WebIconSmallSize];
3413 - (DOMDocument *)mainFrameDocument
3415 // only return the actual value if the state we're in gives NSTreeController
3416 // enough time to release its observers on the old model
3417 if (_private->mainFrameDocumentReady)
3418 return [[self mainFrame] DOMDocument];
3422 - (void)setDrawsBackground:(BOOL)drawsBackground
3424 if (_private->drawsBackground == drawsBackground)
3426 _private->drawsBackground = drawsBackground;
3427 [[self mainFrame] _updateBackgroundAndUpdatesWhileOffscreen];
3430 - (BOOL)drawsBackground
3432 // This method can be called beneath -[NSView dealloc] after we have cleared _private,
3433 // indirectly via -[WebFrameView viewDidMoveToWindow].
3434 return !_private || _private->drawsBackground;
3437 - (void)setShouldUpdateWhileOffscreen:(BOOL)updateWhileOffscreen
3439 if (_private->shouldUpdateWhileOffscreen == updateWhileOffscreen)
3441 _private->shouldUpdateWhileOffscreen = updateWhileOffscreen;
3442 [[self mainFrame] _updateBackgroundAndUpdatesWhileOffscreen];
3445 - (BOOL)shouldUpdateWhileOffscreen
3447 return _private->shouldUpdateWhileOffscreen;
3450 - (void)setCurrentNodeHighlight:(WebNodeHighlight *)nodeHighlight
3452 id old = _private->currentNodeHighlight;
3453 _private->currentNodeHighlight = [nodeHighlight retain];
3457 - (WebNodeHighlight *)currentNodeHighlight
3459 return _private->currentNodeHighlight;
3464 @implementation WebView (WebIBActions)
3466 - (IBAction)takeStringURLFrom: sender
3468 NSString *URLString = [sender stringValue];
3470 [[self mainFrame] loadRequest: [NSURLRequest requestWithURL: [NSURL _web_URLWithDataAsString: URLString]]];
3475 if (!_private->page)
3478 return !!_private->page->backForwardList()->backItem();
3481 - (BOOL)canGoForward
3483 if (!_private->page)
3486 return !!_private->page->backForwardList()->forwardItem();
3489 - (IBAction)goBack:(id)sender
3494 - (IBAction)goForward:(id)sender
3499 - (IBAction)stopLoading:(id)sender
3501 [[self mainFrame] stopLoading];
3504 - (IBAction)reload:(id)sender
3506 [[self mainFrame] reload];
3509 - (IBAction)reloadFromOrigin:(id)sender
3511 [[self mainFrame] reloadFromOrigin];
3514 // FIXME: This code should move into WebCore so that it is not duplicated in each WebKit.
3515 // (This includes canMakeTextSmaller/Larger, makeTextSmaller/Larger, and canMakeTextStandardSize/makeTextStandardSize)
3516 - (BOOL)canMakeTextSmaller
3518 return [self _canZoomOut:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3521 - (IBAction)makeTextSmaller:(id)sender
3523 return [self _zoomOut:sender isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3526 - (BOOL)canMakeTextLarger
3528 return [self _canZoomIn:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3531 - (IBAction)makeTextLarger:(id)sender
3533 return [self _zoomIn:sender isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3536 - (BOOL)canMakeTextStandardSize
3538 return [self _canResetZoom:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3541 - (IBAction)makeTextStandardSize:(id)sender
3543 return [self _resetZoom:sender isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3546 - (IBAction)toggleSmartInsertDelete:(id)sender
3548 [self setSmartInsertDeleteEnabled:![self smartInsertDeleteEnabled]];
3551 - (IBAction)toggleContinuousSpellChecking:(id)sender
3553 [self setContinuousSpellCheckingEnabled:![self isContinuousSpellCheckingEnabled]];
3556 - (BOOL)_responderValidateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item
3558 id responder = [self _responderForResponderOperations];
3559 if (responder != self && [responder respondsToSelector:[item action]]) {
3560 if ([responder respondsToSelector:@selector(validateUserInterfaceItemWithoutDelegate:)])
3561 return [responder validateUserInterfaceItemWithoutDelegate:item];
3562 if ([responder respondsToSelector:@selector(validateUserInterfaceItem:)])
3563 return [responder validateUserInterfaceItem:item];
3569 #define VALIDATE(name) \
3570 else if (action == @selector(name:)) { return [self _responderValidateUserInterfaceItem:item]; }
3572 - (BOOL)validateUserInterfaceItemWithoutDelegate:(id <NSValidatedUserInterfaceItem>)item
3574 SEL action = [item action];
3576 if (action == @selector(goBack:)) {
3577 return [self canGoBack];
3578 } else if (action == @selector(goForward:)) {
3579 return [self canGoForward];
3580 } else if (action == @selector(makeTextLarger:)) {
3581 return [self canMakeTextLarger];
3582 } else if (action == @selector(makeTextSmaller:)) {
3583 return [self canMakeTextSmaller];
3584 } else if (action == @selector(makeTextStandardSize:)) {
3585 return [self canMakeTextStandardSize];
3586 } else if (action == @selector(reload:)) {
3587 return [[self mainFrame] _dataSource] != nil;
3588 } else if (action == @selector(stopLoading:)) {
3589 return [self _isLoading];
3590 } else if (action == @selector(toggleContinuousSpellChecking:)) {
3591 BOOL checkMark = NO;
3593 if ([self _continuousCheckingAllowed]) {
3594 checkMark = [self isContinuousSpellCheckingEnabled];
3597 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
3598 NSMenuItem *menuItem = (NSMenuItem *)item;
3599 [menuItem setState:checkMark ? NSOnState : NSOffState];
3602 #ifndef BUILDING_ON_TIGER
3603 } else if (action == @selector(toggleGrammarChecking:)) {
3604 BOOL checkMark = [self isGrammarCheckingEnabled];
3605 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
3606 NSMenuItem *menuItem = (NSMenuItem *)item;
3607 [menuItem setState:checkMark ? NSOnState : NSOffState];
3612 FOR_EACH_RESPONDER_SELECTOR(VALIDATE)
3617 - (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item
3619 BOOL result = [self validateUserInterfaceItemWithoutDelegate:item];
3620 return CallUIDelegateReturningBoolean(result, self, @selector(webView:validateUserInterfaceItem:defaultValidation:), item, result);
3625 @implementation WebView (WebPendingPublic)
3627 - (void)scheduleInRunLoop:(NSRunLoop *)runLoop forMode:(NSString *)mode
3629 #ifndef BUILDING_ON_TIGER
3630 if (runLoop && mode)
3631 core(self)->addSchedulePair(SchedulePair::create(runLoop, (CFStringRef)mode));
3635 - (void)unscheduleFromRunLoop:(NSRunLoop *)runLoop forMode:(NSString *)mode
3637 #ifndef BUILDING_ON_TIGER
3638 if (runLoop && mode)
3639 core(self)->removeSchedulePair(SchedulePair::create(runLoop, (CFStringRef)mode));
3643 - (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag startInSelection:(BOOL)startInSelection
3645 if (_private->closed)
3648 // Get the frame holding the selection, or start with the main frame
3649 WebFrame *startFrame = [self _selectedOrMainFrame];
3651 // Search the first frame, then all the other frames, in order
3652 NSView <WebDocumentSearching> *startSearchView = nil;
3653 WebFrame *frame = startFrame;
3655 WebFrame *nextFrame = incrementFrame(frame, forward, wrapFlag);
3657 BOOL onlyOneFrame = (frame == nextFrame);
3658 ASSERT(!onlyOneFrame || frame == startFrame);
3660 id <WebDocumentView> view = [[frame frameView] documentView];
3661 if ([view conformsToProtocol:@protocol(WebDocumentSearching)]) {
3662 NSView <WebDocumentSearching> *searchView = (NSView <WebDocumentSearching> *)view;
3664 if (frame == startFrame)
3665 startSearchView = searchView;
3668 // In some cases we have to search some content twice; see comment later in this method.
3669 // We can avoid ever doing this in the common one-frame case by passing YES for wrapFlag
3670 // here, and then bailing out before we get to the code that would search again in the
3672 BOOL wrapOnThisPass = wrapFlag && onlyOneFrame;
3673 if ([searchView conformsToProtocol:@protocol(WebDocumentIncrementalSearching)])
3674 foundString = [(NSView <WebDocumentIncrementalSearching> *)searchView searchFor:string direction:forward caseSensitive:caseFlag wrap:wrapOnThisPass startInSelection:startInSelection];
3676 foundString = [searchView searchFor:string direction:forward caseSensitive:caseFlag wrap:wrapOnThisPass];
3679 if (frame != startFrame)
3680 [startFrame _clearSelection];
3681 [[self window] makeFirstResponder:searchView];
3689 } while (frame && frame != startFrame);
3691 // 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
3692 // 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
3693 // 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
3694 // some content that we already searched on the first pass. In the worst case, we could search the entire contents of this frame twice.
3695 // To fix this, we'd need to add a mechanism to specify a range in which to search.
3696 if (wrapFlag && startSearchView) {
3698 if ([startSearchView conformsToProtocol:@protocol(WebDocumentIncrementalSearching)])
3699 foundString = [(NSView <WebDocumentIncrementalSearching> *)startSearchView searchFor:string direction:forward caseSensitive:caseFlag wrap:YES startInSelection:startInSelection];