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 "DOMCSSStyleDeclarationInternal.h"
33 #import "DOMNodeInternal.h"
34 #import "DOMRangeInternal.h"
35 #import "WebBackForwardListInternal.h"
37 #import "WebChromeClient.h"
38 #import "WebContextMenuClient.h"
39 #import "WebDOMOperationsPrivate.h"
40 #import "WebDataSourceInternal.h"
41 #import "WebDatabaseManagerInternal.h"
42 #import "WebDefaultEditingDelegate.h"
43 #import "WebDefaultPolicyDelegate.h"
44 #import "WebDefaultUIDelegate.h"
45 #import "WebDocument.h"
46 #import "WebDocumentInternal.h"
47 #import "WebDownload.h"
48 #import "WebDownloadInternal.h"
49 #import "WebDragClient.h"
50 #import "WebDynamicScrollBarsViewInternal.h"
51 #import "WebEditingDelegate.h"
52 #import "WebEditorClient.h"
53 #import "WebFormDelegatePrivate.h"
54 #import "WebFrameInternal.h"
55 #import "WebFrameViewInternal.h"
56 #import "WebHTMLRepresentation.h"
57 #import "WebHTMLViewInternal.h"
58 #import "WebHistoryItemInternal.h"
59 #import "WebIconDatabaseInternal.h"
60 #import "WebInspector.h"
61 #import "WebInspectorClient.h"
62 #import "WebKitErrors.h"
63 #import "WebKitLogging.h"
64 #import "WebKitNSStringExtras.h"
65 #import "WebKitStatisticsPrivate.h"
66 #import "WebKitSystemBits.h"
67 #import "WebKitVersionChecks.h"
68 #import "WebLocalizableStrings.h"
69 #import "WebNodeHighlight.h"
70 #import "WebNSDataExtras.h"
71 #import "WebNSDataExtrasPrivate.h"
72 #import "WebNSDictionaryExtras.h"
73 #import "WebNSEventExtras.h"
74 #import "WebNSObjectExtras.h"
75 #import "WebNSPasteboardExtras.h"
76 #import "WebNSPrintOperationExtras.h"
77 #import "WebNSURLExtras.h"
78 #import "WebNSURLRequestExtras.h"
79 #import "WebNSUserDefaultsExtras.h"
80 #import "WebNSViewExtras.h"
81 #import "WebPDFView.h"
82 #import "WebPanelAuthenticationHandler.h"
83 #import "WebPasteboardHelper.h"
84 #import "WebPluginDatabase.h"
85 #import "WebPolicyDelegate.h"
86 #import "WebPreferenceKeysPrivate.h"
87 #import "WebPreferencesPrivate.h"
88 #import "WebScriptDebugDelegate.h"
89 #import "WebSystemInterface.h"
90 #import "WebTextIterator.h"
91 #import "WebUIDelegate.h"
92 #import "WebUIDelegatePrivate.h"
93 #import <CoreFoundation/CFSet.h>
94 #import <Foundation/NSURLConnection.h>
95 #import <WebCore/ApplicationCacheStorage.h>
96 #import <WebCore/Cache.h>
97 #import <WebCore/ColorMac.h>
98 #import <WebCore/Cursor.h>
99 #import <WebCore/Document.h>
100 #import <WebCore/DocumentLoader.h>
101 #import <WebCore/DragController.h>
102 #import <WebCore/DragData.h>
103 #import <WebCore/Editor.h>
104 #import <WebCore/EventHandler.h>
105 #import <WebCore/ExceptionHandlers.h>
106 #import <WebCore/FocusController.h>
107 #import <WebCore/Frame.h>
108 #import <WebCore/FrameLoader.h>
109 #import <WebCore/FrameView.h>
110 #import <WebCore/FrameTree.h>
111 #import <WebCore/GCController.h>
112 #import <WebCore/HTMLNames.h>
113 #import <WebCore/HistoryItem.h>
114 #import <WebCore/IconDatabase.h>
115 #import <WebCore/Logging.h>
116 #import <WebCore/MIMETypeRegistry.h>
117 #import <WebCore/Page.h>
118 #import <WebCore/PageCache.h>
119 #import <WebCore/PageGroup.h>
120 #import <WebCore/PlatformMouseEvent.h>
121 #import <WebCore/ProgressTracker.h>
122 #import <WebCore/RuntimeApplicationChecks.h>
123 #import <WebCore/ScriptController.h>
124 #import <WebCore/ScriptValue.h>
125 #import <WebCore/SelectionController.h>
126 #import <WebCore/Settings.h>
127 #import <WebCore/TextResourceDecoder.h>
128 #import <WebCore/ThreadCheck.h>
129 #import <WebCore/WebCoreObjCExtras.h>
130 #import <WebCore/WebCoreTextRenderer.h>
131 #import <WebCore/WebCoreView.h>
132 #import <WebCore/Widget.h>
133 #import <WebKit/DOM.h>
134 #import <WebKit/DOMExtensions.h>
135 #import <WebKit/DOMPrivate.h>
136 #import <WebKitSystemInterface.h>
137 #import <mach-o/dyld.h>
138 #import <objc/objc-auto.h>
139 #import <objc/objc-runtime.h>
140 #import <runtime/ArrayPrototype.h>
141 #import <runtime/DateInstance.h>
142 #import <runtime/InitializeThreading.h>
143 #import <runtime/JSLock.h>
144 #import <runtime/JSValue.h>
145 #import <wtf/Assertions.h>
146 #import <wtf/HashTraits.h>
147 #import <wtf/RefCountedLeakCounter.h>
148 #import <wtf/RefPtr.h>
149 #import <wtf/StdLibExtras.h>
151 #if ENABLE(DASHBOARD_SUPPORT)
152 #import <WebKit/WebDashboardRegion.h>
155 using namespace WebCore;
158 #if defined(__ppc__) || defined(__ppc64__)
159 #define PROCESSOR "PPC"
160 #elif defined(__i386__) || defined(__x86_64__)
161 #define PROCESSOR "Intel"
163 #error Unknown architecture
166 #define FOR_EACH_RESPONDER_SELECTOR(macro) \
168 macro(alignJustified) \
171 macro(capitalizeWord) \
172 macro(centerSelectionInVisibleArea) \
173 macro(changeAttributes) \
174 macro(changeBaseWritingDirection) \
175 macro(changeBaseWritingDirectionToLTR) \
176 macro(changeBaseWritingDirectionToRTL) \
178 macro(changeDocumentBackgroundColor) \
180 macro(changeSpelling) \
181 macro(checkSpelling) \
187 macro(deleteBackward) \
188 macro(deleteBackwardByDecomposingPreviousCharacter) \
189 macro(deleteForward) \
190 macro(deleteToBeginningOfLine) \
191 macro(deleteToBeginningOfParagraph) \
192 macro(deleteToEndOfLine) \
193 macro(deleteToEndOfParagraph) \
194 macro(deleteToMark) \
195 macro(deleteWordBackward) \
196 macro(deleteWordForward) \
197 macro(ignoreSpelling) \
199 macro(insertBacktab) \
200 macro(insertLineBreak) \
201 macro(insertNewline) \
202 macro(insertNewlineIgnoringFieldEditor) \
203 macro(insertParagraphSeparator) \
205 macro(insertTabIgnoringFieldEditor) \
206 macro(lowercaseWord) \
207 macro(makeBaseWritingDirectionLeftToRight) \
208 macro(makeBaseWritingDirectionRightToLeft) \
209 macro(makeTextWritingDirectionLeftToRight) \
210 macro(makeTextWritingDirectionNatural) \
211 macro(makeTextWritingDirectionRightToLeft) \
212 macro(moveBackward) \
213 macro(moveBackwardAndModifySelection) \
215 macro(moveDownAndModifySelection) \
217 macro(moveForwardAndModifySelection) \
219 macro(moveLeftAndModifySelection) \
220 macro(moveParagraphBackwardAndModifySelection) \
221 macro(moveParagraphForwardAndModifySelection) \
223 macro(moveRightAndModifySelection) \
224 macro(moveToBeginningOfDocument) \
225 macro(moveToBeginningOfDocumentAndModifySelection) \
226 macro(moveToBeginningOfLine) \
227 macro(moveToBeginningOfLineAndModifySelection) \
228 macro(moveToBeginningOfParagraph) \
229 macro(moveToBeginningOfParagraphAndModifySelection) \
230 macro(moveToBeginningOfSentence) \
231 macro(moveToBeginningOfSentenceAndModifySelection) \
232 macro(moveToEndOfDocument) \
233 macro(moveToEndOfDocumentAndModifySelection) \
234 macro(moveToEndOfLine) \
235 macro(moveToEndOfLineAndModifySelection) \
236 macro(moveToEndOfParagraph) \
237 macro(moveToEndOfParagraphAndModifySelection) \
238 macro(moveToEndOfSentence) \
239 macro(moveToEndOfSentenceAndModifySelection) \
240 macro(moveToLeftEndOfLine) \
241 macro(moveToLeftEndOfLineAndModifySelection) \
242 macro(moveToRightEndOfLine) \
243 macro(moveToRightEndOfLineAndModifySelection) \
245 macro(moveUpAndModifySelection) \
246 macro(moveWordBackward) \
247 macro(moveWordBackwardAndModifySelection) \
248 macro(moveWordForward) \
249 macro(moveWordForwardAndModifySelection) \
250 macro(moveWordLeft) \
251 macro(moveWordLeftAndModifySelection) \
252 macro(moveWordRight) \
253 macro(moveWordRightAndModifySelection) \
255 macro(orderFrontSubstitutionsPanel) \
257 macro(pageDownAndModifySelection) \
259 macro(pageUpAndModifySelection) \
261 macro(pasteAsPlainText) \
262 macro(pasteAsRichText) \
264 macro(performFindPanelAction) \
265 macro(scrollLineDown) \
266 macro(scrollLineUp) \
267 macro(scrollPageDown) \
268 macro(scrollPageUp) \
269 macro(scrollToBeginningOfDocument) \
270 macro(scrollToEndOfDocument) \
273 macro(selectParagraph) \
274 macro(selectSentence) \
275 macro(selectToMark) \
278 macro(showGuessPanel) \
279 macro(startSpeaking) \
280 macro(stopSpeaking) \
283 macro(swapWithMark) \
284 macro(takeFindStringFromSelection) \
285 macro(toggleBaseWritingDirection) \
289 macro(uppercaseWord) \
291 macro(yankAndSelect) \
293 #define WebKitOriginalTopPrintingMarginKey @"WebKitOriginalTopMargin"
294 #define WebKitOriginalBottomPrintingMarginKey @"WebKitOriginalBottomMargin"
296 #define KeyboardUIModeDidChangeNotification @"com.apple.KeyboardUIModeDidChange"
297 #define AppleKeyboardUIMode CFSTR("AppleKeyboardUIMode")
298 #define UniversalAccessDomain CFSTR("com.apple.universalaccess")
300 #if USE(ACCELERATED_COMPOSITING)
301 #define UsingAcceleratedCompositingProperty @"_isUsingAcceleratedCompositing"
305 static BOOL s_didSetCacheModel;
306 static WebCacheModel s_cacheModel = WebCacheModelDocumentViewer;
308 static BOOL applicationIsTerminating;
309 static int pluginDatabaseClientCount = 0;
312 static const char webViewIsOpen[] = "At least one WebView is still open.";
315 @interface NSSpellChecker (AppKitSecretsIKnow)
316 - (void)_preflightChosenSpellServer;
319 @interface NSView (AppKitSecretsIKnow)
320 - (NSView *)_hitTest:(NSPoint *)aPoint dragTypes:(NSSet *)types;
321 - (void)_autoscrollForDraggingInfo:(id)dragInfo timeDelta:(NSTimeInterval)repeatDelta;
322 - (BOOL)_shouldAutoscrollForDraggingInfo:(id)dragInfo;
325 @interface NSWindow (AppKitSecretsIKnow)
326 - (id)_oldFirstResponderBeforeBecoming;
329 @interface NSObject (ValidateWithoutDelegate)
330 - (BOOL)validateUserInterfaceItemWithoutDelegate:(id <NSValidatedUserInterfaceItem>)item;
333 @interface _WebSafeForwarder : NSObject
335 id target; // Non-retained. Don't retain delegates.
337 BOOL catchExceptions;
339 - (id)initWithTarget:(id)target defaultTarget:(id)defaultTarget catchExceptions:(BOOL)catchExceptions;
342 @interface WebViewPrivate : NSObject {
347 id UIDelegateForwarder;
348 id resourceProgressDelegate;
351 id policyDelegateForwarder;
352 id frameLoadDelegate;
353 id frameLoadDelegateForwarder;
354 id <WebFormDelegate> formDelegate;
356 id editingDelegateForwarder;
357 id scriptDebugDelegate;
359 WebInspector *inspector;
360 WebNodeHighlight *currentNodeHighlight;
364 float zoomMultiplier;
366 NSString *applicationNameForUserAgent;
368 BOOL userAgentOverridden;
370 WebPreferences *preferences;
371 BOOL useSiteSpecificSpoofing;
373 NSWindow *hostWindow;
375 int programmaticFocusCount;
377 WebResourceDelegateImplementationCache resourceLoadDelegateImplementations;
378 WebFrameLoadDelegateImplementationCache frameLoadDelegateImplementations;
379 WebScriptDebugDelegateImplementationCache scriptDebugDelegateImplementations;
381 void *observationInfo;
384 BOOL shouldCloseWithWindow;
385 BOOL mainFrameDocumentReady;
386 BOOL drawsBackground;
388 BOOL tabKeyCyclesThroughElementsChanged;
389 BOOL becomingFirstResponder;
390 BOOL becomingFirstResponderFromOutside;
391 BOOL hoverFeedbackSuspended;
393 BOOL catchesDelegateExceptions;
395 NSColor *backgroundColor;
397 NSString *mediaStyle;
399 BOOL hasSpellCheckerDocumentTag;
400 NSInteger spellCheckerDocumentTag;
402 BOOL smartInsertDeleteEnabled;
403 BOOL selectTrailingWhitespaceEnabled;
405 #if ENABLE(DASHBOARD_SUPPORT)
406 BOOL dashboardBehaviorAlwaysSendMouseEventsToAllWindows;
407 BOOL dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns;
408 BOOL dashboardBehaviorAlwaysAcceptsFirstMouse;
409 BOOL dashboardBehaviorAllowWheelScrolling;
412 // WebKit has both a global plug-in database and a separate, per WebView plug-in database. Dashboard uses the per WebView database.
413 WebPluginDatabase *pluginDatabase;
415 HashMap<unsigned long, RetainPtr<id> > identifierMap;
417 BOOL _keyboardUIModeAccessed;
418 KeyboardUIMode _keyboardUIMode;
420 BOOL shouldUpdateWhileOffscreen;
422 // When this flag is set, we will not make any subviews underneath this WebView. This means no WebFrameViews and no WebHTMLViews.
423 BOOL useDocumentViews;
425 #if USE(ACCELERATED_COMPOSITING)
426 // When this flag is set, next time a WebHTMLView draws, it needs to temporarily disable screen updates
427 // so that the NSView drawing is visually synchronized with CALayer updates.
428 BOOL needsOneShotDrawingSynchronization;
429 // Number of WebHTMLViews using accelerated compositing. Used to implement _isUsingAcceleratedCompositing.
430 int acceleratedFramesCount;
431 // Run loop observer used to implement the compositing equivalent of -viewWillDraw
432 CFRunLoopObserverRef viewUpdateRunLoopObserver;
435 NSPasteboard *insertionPasteboard;
437 NSSize lastLayoutSize;
441 @interface WebView (WebFileInternal)
442 - (WebFrame *)_selectedOrMainFrame;
444 - (WebFrameView *)_frameViewAtWindowPoint:(NSPoint)point;
445 - (WebFrame *)_focusedFrame;
446 + (void)_preflightSpellChecker;
447 - (BOOL)_continuousCheckingAllowed;
448 - (NSResponder *)_responderForResponderOperations;
451 @interface WebView (WebCallDelegateFunctions)
454 static void patchMailRemoveAttributesMethod();
456 NSString *WebElementDOMNodeKey = @"WebElementDOMNode";
457 NSString *WebElementFrameKey = @"WebElementFrame";
458 NSString *WebElementImageKey = @"WebElementImage";
459 NSString *WebElementImageAltStringKey = @"WebElementImageAltString";
460 NSString *WebElementImageRectKey = @"WebElementImageRect";
461 NSString *WebElementImageURLKey = @"WebElementImageURL";
462 NSString *WebElementIsSelectedKey = @"WebElementIsSelected";
463 NSString *WebElementLinkLabelKey = @"WebElementLinkLabel";
464 NSString *WebElementLinkTargetFrameKey = @"WebElementTargetFrame";
465 NSString *WebElementLinkTitleKey = @"WebElementLinkTitle";
466 NSString *WebElementLinkURLKey = @"WebElementLinkURL";
467 NSString *WebElementSpellingToolTipKey = @"WebElementSpellingToolTip";
468 NSString *WebElementTitleKey = @"WebElementTitle";
469 NSString *WebElementLinkIsLiveKey = @"WebElementLinkIsLive";
470 NSString *WebElementIsContentEditableKey = @"WebElementIsContentEditableKey";
472 NSString *WebViewProgressStartedNotification = @"WebProgressStartedNotification";
473 NSString *WebViewProgressEstimateChangedNotification = @"WebProgressEstimateChangedNotification";
474 NSString *WebViewProgressFinishedNotification = @"WebProgressFinishedNotification";
476 NSString * const WebViewDidBeginEditingNotification = @"WebViewDidBeginEditingNotification";
477 NSString * const WebViewDidChangeNotification = @"WebViewDidChangeNotification";
478 NSString * const WebViewDidEndEditingNotification = @"WebViewDidEndEditingNotification";
479 NSString * const WebViewDidChangeTypingStyleNotification = @"WebViewDidChangeTypingStyleNotification";
480 NSString * const WebViewDidChangeSelectionNotification = @"WebViewDidChangeSelectionNotification";
482 enum { WebViewVersion = 4 };
484 #define timedLayoutSize 4096
486 static NSMutableSet *schemesWithRepresentationsSet;
488 NSString *_WebCanGoBackKey = @"canGoBack";
489 NSString *_WebCanGoForwardKey = @"canGoForward";
490 NSString *_WebEstimatedProgressKey = @"estimatedProgress";
491 NSString *_WebIsLoadingKey = @"isLoading";
492 NSString *_WebMainFrameIconKey = @"mainFrameIcon";
493 NSString *_WebMainFrameTitleKey = @"mainFrameTitle";
494 NSString *_WebMainFrameURLKey = @"mainFrameURL";
495 NSString *_WebMainFrameDocumentKey = @"mainFrameDocument";
497 @interface WebProgressItem : NSObject
500 long long bytesReceived;
501 long long estimatedLength;
505 @implementation WebProgressItem
508 static BOOL continuousSpellCheckingEnabled;
509 #ifndef BUILDING_ON_TIGER
510 static BOOL grammarCheckingEnabled;
512 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
513 static BOOL automaticQuoteSubstitutionEnabled;
514 static BOOL automaticLinkDetectionEnabled;
515 static BOOL automaticDashSubstitutionEnabled;
516 static BOOL automaticTextReplacementEnabled;
517 static BOOL automaticSpellingCorrectionEnabled;
520 @implementation WebViewPrivate
524 JSC::initializeThreading();
525 #ifndef BUILDING_ON_TIGER
526 WebCoreObjCFinalizeOnMainThread(self);
535 JSC::initializeThreading();
538 #if ENABLE(DASHBOARD_SUPPORT)
539 dashboardBehaviorAllowWheelScrolling = YES;
541 shouldCloseWithWindow = objc_collecting_enabled();
543 smartInsertDeleteEnabled = ![[NSUserDefaults standardUserDefaults] objectForKey:WebSmartInsertDeleteEnabled]
544 || [[NSUserDefaults standardUserDefaults] boolForKey:WebSmartInsertDeleteEnabled];
545 continuousSpellCheckingEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebContinuousSpellCheckingEnabled];
546 #ifndef BUILDING_ON_TIGER
547 grammarCheckingEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebGrammarCheckingEnabled];
549 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
550 automaticQuoteSubstitutionEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticQuoteSubstitutionEnabled];
551 automaticLinkDetectionEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticLinkDetectionEnabled];
552 automaticDashSubstitutionEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticDashSubstitutionEnabled];
553 automaticTextReplacementEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticTextReplacementEnabled];
554 automaticSpellingCorrectionEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticSpellingCorrectionEnabled];
559 pluginDatabaseClientCount++;
561 shouldUpdateWhileOffscreen = YES;
568 ASSERT(applicationIsTerminating || !page);
569 ASSERT(applicationIsTerminating || !preferences);
570 ASSERT(!insertionPasteboard);
572 [applicationNameForUserAgent release];
573 [backgroundColor release];
576 [currentNodeHighlight release];
578 [hostWindow release];
580 [policyDelegateForwarder release];
581 [UIDelegateForwarder release];
582 [frameLoadDelegateForwarder release];
583 [editingDelegateForwarder release];
585 [mediaStyle release];
592 ASSERT_MAIN_THREAD();
594 ASSERT(!insertionPasteboard);
599 #if USE(ACCELERATED_COMPOSITING)
600 - (void)_clearViewUpdateRunLoopObserver
602 if (viewUpdateRunLoopObserver) {
603 CFRunLoopObserverInvalidate(viewUpdateRunLoopObserver);
604 CFRelease(viewUpdateRunLoopObserver);
605 viewUpdateRunLoopObserver = 0;
612 @implementation WebView (AllWebViews)
614 static CFSetCallBacks NonRetainingSetCallbacks = {
623 static CFMutableSetRef allWebViewsSet;
625 + (void)_makeAllWebViewsPerformSelector:(SEL)selector
630 [(NSMutableSet *)allWebViewsSet makeObjectsPerformSelector:selector];
633 - (void)_removeFromAllWebViewsSet
636 CFSetRemoveValue(allWebViewsSet, self);
639 - (void)_addToAllWebViewsSet
642 allWebViewsSet = CFSetCreateMutable(NULL, 0, &NonRetainingSetCallbacks);
644 CFSetSetValue(allWebViewsSet, self);
649 @implementation WebView (WebPrivate)
651 static inline int callGestalt(OSType selector)
654 Gestalt(selector, &value);
658 // Uses underscores instead of dots because if "4." ever appears in a user agent string, old DHTML libraries treat it as Netscape 4.
659 static NSString *createMacOSXVersionString()
661 // Can't use -[NSProcessInfo operatingSystemVersionString] because it has too much stuff we don't want.
662 int major = callGestalt(gestaltSystemVersionMajor);
665 int minor = callGestalt(gestaltSystemVersionMinor);
666 int bugFix = callGestalt(gestaltSystemVersionBugFix);
668 return [[NSString alloc] initWithFormat:@"%d_%d_%d", major, minor, bugFix];
670 return [[NSString alloc] initWithFormat:@"%d_%d", major, minor];
671 return [[NSString alloc] initWithFormat:@"%d", major];
674 static NSString *createUserVisibleWebKitVersionString()
676 // If the version is 4 digits long or longer, then the first digit represents
677 // the version of the OS. Our user agent string should not include this first digit,
678 // so strip it off and report the rest as the version. <rdar://problem/4997547>
679 NSString *fullVersion = [[NSBundle bundleForClass:[WebView class]] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey];
680 NSRange nonDigitRange = [fullVersion rangeOfCharacterFromSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]];
681 if (nonDigitRange.location == NSNotFound && [fullVersion length] >= 4)
682 return [[fullVersion substringFromIndex:1] copy];
683 if (nonDigitRange.location != NSNotFound && nonDigitRange.location >= 4)
684 return [[fullVersion substringFromIndex:1] copy];
685 return [fullVersion copy];
688 + (NSString *)_standardUserAgentWithApplicationName:(NSString *)applicationName
690 // Note: Do *not* move the initialization of osVersion nor webKitVersion into the declaration.
691 // Garbage collection won't correctly mark the global variable in that case <rdar://problem/5733674>.
692 static NSString *osVersion;
693 static NSString *webKitVersion;
695 osVersion = createMacOSXVersionString();
697 webKitVersion = createUserVisibleWebKitVersionString();
698 NSString *language = [NSUserDefaults _webkit_preferredLanguageCode];
699 if ([applicationName length])
700 return [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; U; " PROCESSOR " Mac OS X %@; %@) AppleWebKit/%@ (KHTML, like Gecko) %@", osVersion, language, webKitVersion, applicationName];
701 return [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; U; " PROCESSOR " Mac OS X %@; %@) AppleWebKit/%@ (KHTML, like Gecko)", osVersion, language, webKitVersion];
704 static void WebKitInitializeApplicationCachePathIfNecessary()
706 static BOOL initialized = NO;
710 NSString *appName = [[NSBundle mainBundle] bundleIdentifier];
712 appName = [[NSProcessInfo processInfo] processName];
716 NSString* cacheDir = [NSString _webkit_localCacheDirectoryWithBundleIdentifier:appName];
718 cacheStorage().setCacheDirectory(cacheDir);
722 static bool runningLeopardMail()
724 #ifdef BUILDING_ON_LEOPARD
725 return applicationIsAppleMail();
730 static bool runningTigerMail()
732 #ifdef BUILDING_ON_TIGER
733 return applicationIsAppleMail();
738 - (void)_registerDraggedTypes
740 NSArray *editableTypes = [WebHTMLView _insertablePasteboardTypes];
741 NSArray *URLTypes = [NSPasteboard _web_dragTypesForURL];
742 NSMutableSet *types = [[NSMutableSet alloc] initWithArray:editableTypes];
743 [types addObjectsFromArray:URLTypes];
744 [self registerForDraggedTypes:[types allObjects]];
748 - (BOOL)_usesDocumentViews
750 return _private->useDocumentViews;
753 - (void)_commonInitializationWithFrameName:(NSString *)frameName groupName:(NSString *)groupName usesDocumentViews:(BOOL)usesDocumentViews
755 WebCoreThreadViolationCheckRoundTwo();
758 WTF::RefCountedLeakCounter::suppressMessages(webViewIsOpen);
761 WebPreferences *standardPreferences = [WebPreferences standardPreferences];
762 [standardPreferences willAddToWebView];
764 _private->preferences = [standardPreferences retain];
765 _private->catchesDelegateExceptions = YES;
766 _private->mainFrameDocumentReady = NO;
767 _private->drawsBackground = YES;
768 _private->backgroundColor = [[NSColor colorWithDeviceWhite:1 alpha:1] retain];
769 _private->useDocumentViews = usesDocumentViews;
771 WebFrameView *frameView = nil;
772 if (_private->useDocumentViews) {
773 NSRect f = [self frame];
774 frameView = [[WebFrameView alloc] initWithFrame: NSMakeRect(0,0,f.size.width,f.size.height)];
775 [frameView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
776 [self addSubview:frameView];
780 static bool didOneTimeInitialization = false;
781 if (!didOneTimeInitialization) {
782 WebKitInitializeLoggingChannelsIfNecessary();
783 WebCore::InitializeLoggingChannelsIfNecessary();
784 [WebHistoryItem initWindowWatcherIfNecessary];
786 WebKitInitializeDatabasesIfNecessary();
788 WebKitInitializeApplicationCachePathIfNecessary();
789 patchMailRemoveAttributesMethod();
790 didOneTimeInitialization = true;
793 _private->page = new Page(new WebChromeClient(self), new WebContextMenuClient(self), new WebEditorClient(self), new WebDragClient(self), new WebInspectorClient(self));
795 _private->page->settings()->setLocalStorageDatabasePath([[self preferences] _localStorageDatabasePath]);
797 [WebFrame _createMainFrameWithPage:_private->page frameName:frameName frameView:frameView];
799 #ifndef BUILDING_ON_TIGER
800 NSRunLoop *runLoop = [NSRunLoop mainRunLoop];
802 NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
805 if (WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_LOADING_DURING_COMMON_RUNLOOP_MODES))
806 [self scheduleInRunLoop:runLoop forMode:(NSString *)kCFRunLoopCommonModes];
808 [self scheduleInRunLoop:runLoop forMode:NSDefaultRunLoopMode];
810 [self _addToAllWebViewsSet];
811 [self setGroupName:groupName];
813 // If there's already a next key view (e.g., from a nib), wire it up to our
814 // contained frame view. In any case, wire our next key view up to the our
815 // contained frame view. This works together with our becomeFirstResponder
816 // and setNextKeyView overrides.
817 NSView *nextKeyView = [self nextKeyView];
818 if (nextKeyView && nextKeyView != frameView)
819 [frameView setNextKeyView:nextKeyView];
820 [super setNextKeyView:frameView];
824 [self _registerDraggedTypes];
826 WebPreferences *prefs = [self preferences];
827 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:)
828 name:WebPreferencesChangedNotification object:prefs];
830 // Post a notification so the WebCore settings update.
831 [[self preferences] _postPreferencesChangesNotification];
833 if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_LOCAL_RESOURCE_SECURITY_RESTRICTION)) {
834 // Originally, we allowed all local loads.
835 FrameLoader::setLocalLoadPolicy(FrameLoader::AllowLocalLoadsForAll);
836 } else if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_MORE_STRICT_LOCAL_RESOURCE_SECURITY_RESTRICTION)) {
837 // Later, we allowed local loads for local URLs and documents loaded
838 // with substitute data.
839 FrameLoader::setLocalLoadPolicy(FrameLoader::AllowLocalLoadsForLocalAndSubstituteData);
843 - (id)_initWithFrame:(NSRect)f frameName:(NSString *)frameName groupName:(NSString *)groupName usesDocumentViews:(BOOL)usesDocumentViews
845 self = [super initWithFrame:f];
849 #ifdef ENABLE_WEBKIT_UNSET_DYLD_FRAMEWORK_PATH
850 // DYLD_FRAMEWORK_PATH is used so Safari will load the development version of WebKit, which
851 // may not work with other WebKit applications. Unsetting DYLD_FRAMEWORK_PATH removes the
852 // need for Safari to unset it to prevent it from being passed to applications it launches.
853 // Unsetting it when a WebView is first created is as good a place as any.
854 // See <http://bugs.webkit.org/show_bug.cgi?id=4286> for more details.
855 if (getenv("WEBKIT_UNSET_DYLD_FRAMEWORK_PATH")) {
856 unsetenv("DYLD_FRAMEWORK_PATH");
857 unsetenv("WEBKIT_UNSET_DYLD_FRAMEWORK_PATH");
861 _private = [[WebViewPrivate alloc] init];
862 [self _commonInitializationWithFrameName:frameName groupName:groupName usesDocumentViews:usesDocumentViews];
863 [self setMaintainsBackForwardList: YES];
867 - (void)_boundsChanged
869 if (!NSEqualSizes(_private->lastLayoutSize, [self bounds].size)) {
870 Frame* frame = core([self mainFrame]);
871 // FIXME: Viewless WebKit is broken with Safari banners (e.g., the Find banner). We'll have to figure out a way for
872 // Safari to communicate that this space is being consumed. For WebKit with document views, there's no
873 // need to do an explicit resize, since WebFrameViews have auto resizing turned on and will handle changing
874 // their bounds automatically. See <rdar://problem/6835573> for details.
875 if (!_private->useDocumentViews)
876 frame->view()->resize([self bounds].size.width, [self bounds].size.height);
877 frame->view()->setNeedsLayout();
878 [self setNeedsDisplay:YES];
879 _private->lastLayoutSize = [self bounds].size;
883 - (BOOL)_mustDrawUnionedRect:(NSRect)rect singleRects:(const NSRect *)rects count:(NSInteger)count
885 // If count == 0 here, use the rect passed in for drawing. This is a workaround for:
886 // <rdar://problem/3908282> REGRESSION (Mail): No drag image dragging selected text in Blot and Mail
887 // The reason for the workaround is that this method is called explicitly from the code
888 // to generate a drag image, and at that time, getRectsBeingDrawn:count: will return a zero count.
889 const int cRectThreshold = 10;
890 const float cWastedSpaceThreshold = 0.75f;
891 BOOL useUnionedRect = (count <= 1) || (count > cRectThreshold);
892 if (!useUnionedRect) {
893 // Attempt to guess whether or not we should use the unioned rect or the individual rects.
894 // We do this by computing the percentage of "wasted space" in the union. If that wasted space
895 // is too large, then we will do individual rect painting instead.
896 float unionPixels = (rect.size.width * rect.size.height);
897 float singlePixels = 0;
898 for (int i = 0; i < count; ++i)
899 singlePixels += rects[i].size.width * rects[i].size.height;
900 float wastedSpace = 1 - (singlePixels / unionPixels);
901 if (wastedSpace <= cWastedSpaceThreshold)
902 useUnionedRect = YES;
904 return useUnionedRect;
907 - (void)drawSingleRect:(NSRect)rect
909 ASSERT(!_private->useDocumentViews);
911 [NSGraphicsContext saveGraphicsState];
915 [[self mainFrame] _drawRect:rect contentsOnly:NO];
917 WebView *webView = [self _webView];
918 [[webView _UIDelegateForwarder] webView:webView didDrawRect:rect];
920 if (WebNodeHighlight *currentHighlight = [webView currentNodeHighlight])
921 [currentHighlight setNeedsUpdateInTargetViewRect:rect];
923 [NSGraphicsContext restoreGraphicsState];
924 } @catch (NSException *localException) {
925 [NSGraphicsContext restoreGraphicsState];
926 LOG_ERROR("Exception caught while drawing: %@", localException);
927 [localException raise];
933 return _private && !_private->useDocumentViews;
936 #if USE(ACCELERATED_COMPOSITING) || !defined(BUILDING_ON_TIGER)
937 - (void)_viewWillDrawInternal
939 Frame* frame = core([self mainFrame]);
940 if (frame && frame->view())
941 frame->view()->layoutIfNeededRecursive();
945 #ifndef BUILDING_ON_TIGER
949 if (!_private->useDocumentViews)
950 [self _viewWillDrawInternal];
951 [super viewWillDraw];
957 - (void)drawRect:(NSRect)rect
959 if (_private->useDocumentViews)
960 return [super drawRect:rect];
962 ASSERT_MAIN_THREAD();
966 [self getRectsBeingDrawn:&rects count:&count];
969 if ([self _mustDrawUnionedRect:rect singleRects:rects count:count])
970 [self drawSingleRect:rect];
972 for (int i = 0; i < count; ++i)
973 [self drawSingleRect:rects[i]];
976 + (NSArray *)_supportedMIMETypes
978 // Load the plug-in DB allowing plug-ins to install types.
979 [WebPluginDatabase sharedDatabase];
980 return [[WebFrameView _viewTypesAllowImageTypeOmission:NO] allKeys];
983 + (NSArray *)_supportedFileExtensions
985 NSMutableSet *extensions = [[NSMutableSet alloc] init];
986 NSArray *MIMETypes = [self _supportedMIMETypes];
987 NSEnumerator *enumerator = [MIMETypes objectEnumerator];
989 while ((MIMEType = [enumerator nextObject]) != nil) {
990 NSArray *extensionsForType = WKGetExtensionsForMIMEType(MIMEType);
991 if (extensionsForType) {
992 [extensions addObjectsFromArray:extensionsForType];
995 NSArray *uniqueExtensions = [extensions allObjects];
996 [extensions release];
997 return uniqueExtensions;
1000 + (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType
1002 MIMEType = [MIMEType lowercaseString];
1003 Class viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:YES] _webkit_objectForMIMEType:MIMEType];
1004 Class repClass = [[WebDataSource _repTypesAllowImageTypeOmission:YES] _webkit_objectForMIMEType:MIMEType];
1006 if (!viewClass || !repClass || [[WebPDFView supportedMIMETypes] containsObject:MIMEType]) {
1007 // Our optimization to avoid loading the plug-in DB and image types for the HTML case failed.
1008 // Load the plug-in DB allowing plug-ins to install types.
1009 [WebPluginDatabase sharedDatabase];
1011 // Load the image types and get the view class and rep class. This should be the fullest picture of all handled types.
1012 viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:NO] _webkit_objectForMIMEType:MIMEType];
1013 repClass = [[WebDataSource _repTypesAllowImageTypeOmission:NO] _webkit_objectForMIMEType:MIMEType];
1016 if (viewClass && repClass) {
1017 // Special-case WebHTMLView for text types that shouldn't be shown.
1018 if (viewClass == [WebHTMLView class] &&
1019 repClass == [WebHTMLRepresentation class] &&
1020 [[WebHTMLView unsupportedTextMIMETypes] containsObject:MIMEType]) {
1024 *vClass = viewClass;
1033 - (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType
1035 if ([[self class] _viewClass:vClass andRepresentationClass:rClass forMIMEType:MIMEType])
1038 if (_private->pluginDatabase) {
1039 WebBasePluginPackage *pluginPackage = [_private->pluginDatabase pluginForMIMEType:MIMEType];
1040 if (pluginPackage) {
1042 *vClass = [WebHTMLView class];
1044 *rClass = [WebHTMLRepresentation class];
1052 + (void)_setAlwaysUseATSU:(BOOL)f
1054 [self _setAlwaysUsesComplexTextCodePath:f];
1057 + (void)_setAlwaysUsesComplexTextCodePath:(BOOL)f
1059 WebCoreSetAlwaysUsesComplexTextCodePath(f);
1062 + (BOOL)canCloseAllWebViews
1064 return DOMWindow::dispatchAllPendingBeforeUnloadEvents();
1067 + (void)closeAllWebViews
1069 DOMWindow::dispatchAllPendingUnloadEvents();
1071 // This will close the WebViews in a random order. Change this if close order is important.
1072 NSEnumerator *enumerator = [(NSMutableSet *)allWebViewsSet objectEnumerator];
1073 while (WebView *webView = [enumerator nextObject])
1077 + (BOOL)canShowFile:(NSString *)path
1079 return [[self class] canShowMIMEType:[WebView _MIMETypeForFile:path]];
1082 + (NSString *)suggestedFileExtensionForMIMEType:(NSString *)type
1084 return WKGetPreferredExtensionForMIMEType(type);
1089 return !_private || _private->closed;
1092 - (void)_closePluginDatabases
1094 pluginDatabaseClientCount--;
1096 // Close both sets of plug-in databases because plug-ins need an opportunity to clean up files, etc.
1098 // Unload the WebView local plug-in database.
1099 if (_private->pluginDatabase) {
1100 [_private->pluginDatabase destroyAllPluginInstanceViews];
1101 [_private->pluginDatabase close];
1102 [_private->pluginDatabase release];
1103 _private->pluginDatabase = nil;
1106 // Keep the global plug-in database active until the app terminates to avoid having to reload plug-in bundles.
1107 if (!pluginDatabaseClientCount && applicationIsTerminating)
1108 [WebPluginDatabase closeSharedDatabase];
1111 - (void)_closeWithFastTeardown
1114 WTF::RefCountedLeakCounter::suppressMessages("At least one WebView was closed with fast teardown.");
1117 _private->closed = YES;
1119 [self _closePluginDatabases];
1122 static bool fastDocumentTeardownEnabled()
1125 static bool enabled = ![[NSUserDefaults standardUserDefaults] boolForKey:WebKitEnableFullDocumentTeardownPreferenceKey];
1127 static bool initialized = false;
1128 static bool enabled = false;
1130 // This allows debug builds to default to not have fast teardown, so leak checking still works.
1131 // But still allow the WebKitEnableFullDocumentTeardown default to override it if present.
1132 NSNumber *setting = [[NSUserDefaults standardUserDefaults] objectForKey:WebKitEnableFullDocumentTeardownPreferenceKey];
1134 enabled = ![setting boolValue];
1141 // _close is here only for backward compatibility; clients and subclasses should use
1142 // public method -close instead.
1145 if (!_private || _private->closed)
1149 WTF::RefCountedLeakCounter::cancelMessageSuppression(webViewIsOpen);
1152 // To quit the apps fast we skip document teardown, except plugins
1153 // need to be destroyed and unloaded.
1154 if (applicationIsTerminating && fastDocumentTeardownEnabled()) {
1155 [self _closeWithFastTeardown];
1159 if (Frame* mainFrame = core([self mainFrame]))
1160 mainFrame->loader()->detachFromParent();
1162 [self _removeFromAllWebViewsSet];
1163 [self setHostWindow:nil];
1165 [self setDownloadDelegate:nil];
1166 [self setEditingDelegate:nil];
1167 [self setFrameLoadDelegate:nil];
1168 [self setPolicyDelegate:nil];
1169 [self setResourceLoadDelegate:nil];
1170 [self setScriptDebugDelegate:nil];
1171 [self setUIDelegate:nil];
1173 [_private->inspector webViewClosed];
1175 // setHostWindow:nil must be called before this value is set (see 5408186)
1176 _private->closed = YES;
1178 // To avoid leaks, call removeDragCaret in case it wasn't called after moveDragCaretToPoint.
1179 [self removeDragCaret];
1181 // Deleteing the WebCore::Page will clear the page cache so we call destroy on
1182 // all the plug-ins in the page cache to break any retain cycles.
1183 // See comment in HistoryItem::releaseAllPendingPageCaches() for more information.
1184 delete _private->page;
1187 if (_private->hasSpellCheckerDocumentTag) {
1188 [[NSSpellChecker sharedSpellChecker] closeSpellDocumentWithTag:_private->spellCheckerDocumentTag];
1189 _private->hasSpellCheckerDocumentTag = NO;
1192 #if USE(ACCELERATED_COMPOSITING)
1193 [_private _clearViewUpdateRunLoopObserver];
1196 [[NSDistributedNotificationCenter defaultCenter] removeObserver:self];
1197 [[NSNotificationCenter defaultCenter] removeObserver:self];
1199 [WebPreferences _removeReferenceForIdentifier:[self preferencesIdentifier]];
1201 WebPreferences *preferences = _private->preferences;
1202 _private->preferences = nil;
1203 [preferences didRemoveFromWebView];
1204 [preferences release];
1206 [self _closePluginDatabases];
1209 // Need this to make leak messages accurate.
1210 if (applicationIsTerminating) {
1211 gcController().garbageCollectNow();
1212 [WebCache setDisabled:YES];
1217 + (NSString *)_MIMETypeForFile:(NSString *)path
1219 NSString *extension = [path pathExtension];
1220 NSString *MIMEType = nil;
1222 // Get the MIME type from the extension.
1223 if ([extension length] != 0) {
1224 MIMEType = WKGetMIMETypeForExtension(extension);
1227 // If we can't get a known MIME type from the extension, sniff.
1228 if ([MIMEType length] == 0 || [MIMEType isEqualToString:@"application/octet-stream"]) {
1229 NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:path];
1230 NSData *data = [handle readDataOfLength:WEB_GUESS_MIME_TYPE_PEEK_LENGTH];
1232 if ([data length] != 0) {
1233 MIMEType = [data _webkit_guessedMIMEType];
1235 if ([MIMEType length] == 0) {
1236 MIMEType = @"application/octet-stream";
1243 - (WebDownload *)_downloadURL:(NSURL *)URL
1247 NSURLRequest *request = [[NSURLRequest alloc] initWithURL:URL];
1248 WebDownload *download = [WebDownload _downloadWithRequest:request
1249 delegate:_private->downloadDelegate
1256 - (WebView *)_openNewWindowWithRequest:(NSURLRequest *)request
1258 NSDictionary *features = [[NSDictionary alloc] init];
1259 WebView *newWindowWebView = [[self _UIDelegateForwarder] webView:self
1260 createWebViewWithRequest:nil
1261 windowFeatures:features];
1263 if (!newWindowWebView)
1266 CallUIDelegate(newWindowWebView, @selector(webViewShow:));
1267 return newWindowWebView;
1270 - (WebInspector *)inspector
1272 if (!_private->inspector)
1273 _private->inspector = [[WebInspector alloc] initWithWebView:self];
1274 return _private->inspector;
1277 - (WebCore::Page*)page
1279 return _private->page;
1282 - (NSMenu *)_menuForElement:(NSDictionary *)element defaultItems:(NSArray *)items
1284 NSArray *defaultMenuItems = [[WebDefaultUIDelegate sharedUIDelegate] webView:self contextMenuItemsForElement:element defaultMenuItems:items];
1286 NSArray *menuItems = CallUIDelegate(self, @selector(webView:contextMenuItemsForElement:defaultMenuItems:), element, defaultMenuItems);
1290 unsigned count = [menuItems count];
1294 NSMenu *menu = [[NSMenu alloc] init];
1295 for (unsigned i = 0; i < count; i++)
1296 [menu addItem:[menuItems objectAtIndex:i]];
1298 return [menu autorelease];
1301 - (void)_mouseDidMoveOverElement:(NSDictionary *)dictionary modifierFlags:(NSUInteger)modifierFlags
1303 // We originally intended to call this delegate method sometimes with a nil dictionary, but due to
1304 // a bug dating back to WebKit 1.0 this delegate was never called with nil! Unfortunately we can't
1305 // start calling this with nil since it will break Adobe Help Viewer, and possibly other clients.
1308 CallUIDelegate(self, @selector(webView:mouseDidMoveOverElement:modifierFlags:), dictionary, modifierFlags);
1311 - (void)_loadBackForwardListFromOtherView:(WebView *)otherView
1313 if (!_private->page)
1316 if (!otherView->_private->page)
1319 // It turns out the right combination of behavior is done with the back/forward load
1320 // type. (See behavior matrix at the top of WebFramePrivate.) So we copy all the items
1321 // in the back forward list, and go to the current one.
1323 BackForwardList* backForwardList = _private->page->backForwardList();
1324 ASSERT(!backForwardList->currentItem()); // destination list should be empty
1326 BackForwardList* otherBackForwardList = otherView->_private->page->backForwardList();
1327 if (!otherBackForwardList->currentItem())
1328 return; // empty back forward list, bail
1330 HistoryItem* newItemToGoTo = 0;
1332 int lastItemIndex = otherBackForwardList->forwardListCount();
1333 for (int i = -otherBackForwardList->backListCount(); i <= lastItemIndex; ++i) {
1335 // If this item is showing , save away its current scroll and form state,
1336 // since that might have changed since loading and it is normally not saved
1337 // until we leave that page.
1338 otherView->_private->page->mainFrame()->loader()->saveDocumentAndScrollState();
1340 RefPtr<HistoryItem> newItem = otherBackForwardList->itemAtIndex(i)->copy();
1342 newItemToGoTo = newItem.get();
1343 backForwardList->addItem(newItem.release());
1346 ASSERT(newItemToGoTo);
1347 _private->page->goToItem(newItemToGoTo, FrameLoadTypeIndexedBackForward);
1350 - (void)_setFormDelegate: (id<WebFormDelegate>)delegate
1352 _private->formDelegate = delegate;
1355 - (id<WebFormDelegate>)_formDelegate
1357 return _private->formDelegate;
1360 - (BOOL)_needsAdobeFrameReloadingQuirk
1362 static BOOL checked = NO;
1363 static BOOL needsQuirk = NO;
1368 needsQuirk = WKAppVersionCheckLessThan(@"com.adobe.Acrobat", -1, 9.0)
1369 || WKAppVersionCheckLessThan(@"com.adobe.Acrobat.Pro", -1, 9.0)
1370 || WKAppVersionCheckLessThan(@"com.adobe.Reader", -1, 9.0)
1371 || WKAppVersionCheckLessThan(@"com.adobe.distiller", -1, 9.0)
1372 || WKAppVersionCheckLessThan(@"com.adobe.Contribute", -1, 4.2)
1373 || WKAppVersionCheckLessThan(@"com.adobe.dreamweaver-9.0", -1, 9.1)
1374 || WKAppVersionCheckLessThan(@"com.macromedia.fireworks", -1, 9.1)
1375 || WKAppVersionCheckLessThan(@"com.adobe.InCopy", -1, 5.1)
1376 || WKAppVersionCheckLessThan(@"com.adobe.InDesign", -1, 5.1)
1377 || WKAppVersionCheckLessThan(@"com.adobe.Soundbooth", -1, 2);
1383 - (BOOL)_needsKeyboardEventDisambiguationQuirks
1385 static BOOL checked = NO;
1386 static BOOL needsQuirks = NO;
1391 needsQuirks = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_IE_COMPATIBLE_KEYBOARD_EVENT_DISPATCH) && !applicationIsSafari();
1397 - (void)_preferencesChangedNotification:(NSNotification *)notification
1399 WebPreferences *preferences = (WebPreferences *)[notification object];
1400 ASSERT(preferences == [self preferences]);
1402 if (!_private->userAgentOverridden)
1403 _private->userAgent = String();
1405 // Cache this value so we don't have to read NSUserDefaults on each page load
1406 _private->useSiteSpecificSpoofing = [preferences _useSiteSpecificSpoofing];
1408 // Update corresponding WebCore Settings object.
1409 if (!_private->page)
1412 Settings* settings = _private->page->settings();
1414 settings->setCursiveFontFamily([preferences cursiveFontFamily]);
1415 settings->setDefaultFixedFontSize([preferences defaultFixedFontSize]);
1416 settings->setDefaultFontSize([preferences defaultFontSize]);
1417 settings->setDefaultTextEncodingName([preferences defaultTextEncodingName]);
1418 settings->setUsesEncodingDetector([preferences usesEncodingDetector]);
1419 settings->setFantasyFontFamily([preferences fantasyFontFamily]);
1420 settings->setFixedFontFamily([preferences fixedFontFamily]);
1421 settings->setForceFTPDirectoryListings([preferences _forceFTPDirectoryListings]);
1422 settings->setFTPDirectoryTemplatePath([preferences _ftpDirectoryTemplatePath]);
1423 settings->setLocalStorageDatabasePath([preferences _localStorageDatabasePath]);
1424 settings->setJavaEnabled([preferences isJavaEnabled]);
1425 settings->setJavaScriptEnabled([preferences isJavaScriptEnabled]);
1426 settings->setWebSecurityEnabled([preferences isWebSecurityEnabled]);
1427 settings->setAllowUniversalAccessFromFileURLs([preferences allowUniversalAccessFromFileURLs]);
1428 settings->setJavaScriptCanOpenWindowsAutomatically([preferences javaScriptCanOpenWindowsAutomatically]);
1429 settings->setMinimumFontSize([preferences minimumFontSize]);
1430 settings->setMinimumLogicalFontSize([preferences minimumLogicalFontSize]);
1431 settings->setPluginsEnabled([preferences arePlugInsEnabled]);
1432 settings->setDatabasesEnabled([preferences databasesEnabled]);
1433 settings->setLocalStorageEnabled([preferences localStorageEnabled]);
1434 settings->setPrivateBrowsingEnabled([preferences privateBrowsingEnabled]);
1435 settings->setSansSerifFontFamily([preferences sansSerifFontFamily]);
1436 settings->setSerifFontFamily([preferences serifFontFamily]);
1437 settings->setStandardFontFamily([preferences standardFontFamily]);
1438 settings->setLoadsImagesAutomatically([preferences loadsImagesAutomatically]);
1439 settings->setShouldPrintBackgrounds([preferences shouldPrintBackgrounds]);
1440 settings->setTextAreasAreResizable([preferences textAreasAreResizable]);
1441 settings->setShrinksStandaloneImagesToFit([preferences shrinksStandaloneImagesToFit]);
1442 settings->setEditableLinkBehavior(core([preferences editableLinkBehavior]));
1443 settings->setTextDirectionSubmenuInclusionBehavior(core([preferences textDirectionSubmenuInclusionBehavior]));
1444 settings->setDOMPasteAllowed([preferences isDOMPasteAllowed]);
1445 settings->setUsesPageCache([self usesPageCache]);
1446 settings->setShowsURLsInToolTips([preferences showsURLsInToolTips]);
1447 settings->setDeveloperExtrasEnabled([preferences developerExtrasEnabled]);
1448 settings->setAuthorAndUserStylesEnabled([preferences authorAndUserStylesEnabled]);
1449 settings->setApplicationChromeMode([preferences applicationChromeModeEnabled]);
1450 if ([preferences userStyleSheetEnabled]) {
1451 NSString* location = [[preferences userStyleSheetLocation] _web_originalDataAsString];
1452 settings->setUserStyleSheetLocation([NSURL URLWithString:(location ? location : @"")]);
1454 settings->setUserStyleSheetLocation([NSURL URLWithString:@""]);
1455 settings->setNeedsAdobeFrameReloadingQuirk([self _needsAdobeFrameReloadingQuirk]);
1456 settings->setNeedsKeyboardEventDisambiguationQuirks([self _needsKeyboardEventDisambiguationQuirks]);
1457 settings->setNeedsLeopardMailQuirks(runningLeopardMail());
1458 settings->setNeedsTigerMailQuirks(runningTigerMail());
1459 settings->setNeedsSiteSpecificQuirks(_private->useSiteSpecificSpoofing);
1460 settings->setWebArchiveDebugModeEnabled([preferences webArchiveDebugModeEnabled]);
1461 settings->setOfflineWebApplicationCacheEnabled([preferences offlineWebApplicationCacheEnabled]);
1462 settings->setZoomsTextOnly([preferences zoomsTextOnly]);
1463 settings->setEnforceCSSMIMETypeInStrictMode(!WKAppVersionCheckLessThan(@"com.apple.iWeb", -1, 2.1));
1466 static inline IMP getMethod(id o, SEL s)
1468 return [o respondsToSelector:s] ? [o methodForSelector:s] : 0;
1471 - (void)_cacheResourceLoadDelegateImplementations
1473 WebResourceDelegateImplementationCache *cache = &_private->resourceLoadDelegateImplementations;
1474 id delegate = _private->resourceProgressDelegate;
1477 bzero(cache, sizeof(WebResourceDelegateImplementationCache));
1481 cache->didCancelAuthenticationChallengeFunc = getMethod(delegate, @selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:));
1482 cache->didFailLoadingWithErrorFromDataSourceFunc = getMethod(delegate, @selector(webView:resource:didFailLoadingWithError:fromDataSource:));
1483 cache->didFinishLoadingFromDataSourceFunc = getMethod(delegate, @selector(webView:resource:didFinishLoadingFromDataSource:));
1484 cache->didLoadResourceFromMemoryCacheFunc = getMethod(delegate, @selector(webView:didLoadResourceFromMemoryCache:response:length:fromDataSource:));
1485 cache->didReceiveAuthenticationChallengeFunc = getMethod(delegate, @selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:));
1486 cache->didReceiveContentLengthFunc = getMethod(delegate, @selector(webView:resource:didReceiveContentLength:fromDataSource:));
1487 cache->didReceiveResponseFunc = getMethod(delegate, @selector(webView:resource:didReceiveResponse:fromDataSource:));
1488 cache->identifierForRequestFunc = getMethod(delegate, @selector(webView:identifierForInitialRequest:fromDataSource:));
1489 cache->plugInFailedWithErrorFunc = getMethod(delegate, @selector(webView:plugInFailedWithError:dataSource:));
1490 cache->willCacheResponseFunc = getMethod(delegate, @selector(webView:resource:willCacheResponse:fromDataSource:));
1491 cache->willSendRequestFunc = getMethod(delegate, @selector(webView:resource:willSendRequest:redirectResponse:fromDataSource:));
1492 cache->shouldUseCredentialStorageFunc = getMethod(delegate, @selector(webView:resource:shouldUseCredentialStorageForDataSource:));
1495 WebResourceDelegateImplementationCache* WebViewGetResourceLoadDelegateImplementations(WebView *webView)
1497 static WebResourceDelegateImplementationCache empty;
1500 return &webView->_private->resourceLoadDelegateImplementations;
1503 - (void)_cacheFrameLoadDelegateImplementations
1505 WebFrameLoadDelegateImplementationCache *cache = &_private->frameLoadDelegateImplementations;
1506 id delegate = _private->frameLoadDelegate;
1509 bzero(cache, sizeof(WebFrameLoadDelegateImplementationCache));
1513 cache->didCancelClientRedirectForFrameFunc = getMethod(delegate, @selector(webView:didCancelClientRedirectForFrame:));
1514 cache->didChangeLocationWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didChangeLocationWithinPageForFrame:));
1515 cache->didClearWindowObjectForFrameFunc = getMethod(delegate, @selector(webView:didClearWindowObject:forFrame:));
1516 cache->didCommitLoadForFrameFunc = getMethod(delegate, @selector(webView:didCommitLoadForFrame:));
1517 cache->didFailLoadWithErrorForFrameFunc = getMethod(delegate, @selector(webView:didFailLoadWithError:forFrame:));
1518 cache->didFailProvisionalLoadWithErrorForFrameFunc = getMethod(delegate, @selector(webView:didFailProvisionalLoadWithError:forFrame:));
1519 cache->didFinishDocumentLoadForFrameFunc = getMethod(delegate, @selector(webView:didFinishDocumentLoadForFrame:));
1520 cache->didFinishLoadForFrameFunc = getMethod(delegate, @selector(webView:didFinishLoadForFrame:));
1521 cache->didFirstLayoutInFrameFunc = getMethod(delegate, @selector(webView:didFirstLayoutInFrame:));
1522 cache->didFirstVisuallyNonEmptyLayoutInFrameFunc = getMethod(delegate, @selector(webView:didFirstVisuallyNonEmptyLayoutInFrame:));
1523 cache->didHandleOnloadEventsForFrameFunc = getMethod(delegate, @selector(webView:didHandleOnloadEventsForFrame:));
1524 cache->didReceiveIconForFrameFunc = getMethod(delegate, @selector(webView:didReceiveIcon:forFrame:));
1525 cache->didReceiveServerRedirectForProvisionalLoadForFrameFunc = getMethod(delegate, @selector(webView:didReceiveServerRedirectForProvisionalLoadForFrame:));
1526 cache->didReceiveTitleForFrameFunc = getMethod(delegate, @selector(webView:didReceiveTitle:forFrame:));
1527 cache->didStartProvisionalLoadForFrameFunc = getMethod(delegate, @selector(webView:didStartProvisionalLoadForFrame:));
1528 cache->willCloseFrameFunc = getMethod(delegate, @selector(webView:willCloseFrame:));
1529 cache->willPerformClientRedirectToURLDelayFireDateForFrameFunc = getMethod(delegate, @selector(webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:));
1530 cache->windowScriptObjectAvailableFunc = getMethod(delegate, @selector(webView:windowScriptObjectAvailable:));
1533 WebFrameLoadDelegateImplementationCache* WebViewGetFrameLoadDelegateImplementations(WebView *webView)
1535 static WebFrameLoadDelegateImplementationCache empty;
1538 return &webView->_private->frameLoadDelegateImplementations;
1541 - (void)_cacheScriptDebugDelegateImplementations
1543 WebScriptDebugDelegateImplementationCache *cache = &_private->scriptDebugDelegateImplementations;
1544 id delegate = _private->scriptDebugDelegate;
1547 bzero(cache, sizeof(WebScriptDebugDelegateImplementationCache));
1551 cache->didParseSourceFunc = getMethod(delegate, @selector(webView:didParseSource:baseLineNumber:fromURL:sourceId:forWebFrame:));
1552 if (cache->didParseSourceFunc)
1553 cache->didParseSourceExpectsBaseLineNumber = YES;
1555 cache->didParseSourceFunc = getMethod(delegate, @selector(webView:didParseSource:fromURL:sourceId:forWebFrame:));
1557 cache->failedToParseSourceFunc = getMethod(delegate, @selector(webView:failedToParseSource:baseLineNumber:fromURL:withError:forWebFrame:));
1558 cache->didEnterCallFrameFunc = getMethod(delegate, @selector(webView:didEnterCallFrame:sourceId:line:forWebFrame:));
1559 cache->willExecuteStatementFunc = getMethod(delegate, @selector(webView:willExecuteStatement:sourceId:line:forWebFrame:));
1560 cache->willLeaveCallFrameFunc = getMethod(delegate, @selector(webView:willLeaveCallFrame:sourceId:line:forWebFrame:));
1561 cache->exceptionWasRaisedFunc = getMethod(delegate, @selector(webView:exceptionWasRaised:sourceId:line:forWebFrame:));
1564 WebScriptDebugDelegateImplementationCache* WebViewGetScriptDebugDelegateImplementations(WebView *webView)
1566 static WebScriptDebugDelegateImplementationCache empty;
1569 return &webView->_private->scriptDebugDelegateImplementations;
1572 - (id)_policyDelegateForwarder
1574 if (!_private->policyDelegateForwarder)
1575 _private->policyDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->policyDelegate defaultTarget:[WebDefaultPolicyDelegate sharedPolicyDelegate] catchExceptions:_private->catchesDelegateExceptions];
1576 return _private->policyDelegateForwarder;
1579 - (id)_UIDelegateForwarder
1581 if (!_private->UIDelegateForwarder)
1582 _private->UIDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->UIDelegate defaultTarget:[WebDefaultUIDelegate sharedUIDelegate] catchExceptions:_private->catchesDelegateExceptions];
1583 return _private->UIDelegateForwarder;
1586 - (id)_editingDelegateForwarder
1588 // This can be called during window deallocation by QTMovieView in the QuickTime Cocoa Plug-in.
1589 // Not sure if that is a bug or not.
1593 if (!_private->editingDelegateForwarder)
1594 _private->editingDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->editingDelegate defaultTarget:[WebDefaultEditingDelegate sharedEditingDelegate] catchExceptions:_private->catchesDelegateExceptions];
1595 return _private->editingDelegateForwarder;
1598 - (void)_closeWindow
1600 [[self _UIDelegateForwarder] webViewClose:self];
1603 + (void)_unregisterViewClassAndRepresentationClassForMIMEType:(NSString *)MIMEType
1605 [[WebFrameView _viewTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType];
1606 [[WebDataSource _repTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType];
1608 // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
1609 // in the WebCore MIMEType registry. For now we're doing this in a safe, limited manner
1610 // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
1611 MIMETypeRegistry::getSupportedNonImageMIMETypes().remove(MIMEType);
1614 + (void)_registerViewClass:(Class)viewClass representationClass:(Class)representationClass forURLScheme:(NSString *)URLScheme
1616 NSString *MIMEType = [self _generatedMIMETypeForURLScheme:URLScheme];
1617 [self registerViewClass:viewClass representationClass:representationClass forMIMEType:MIMEType];
1619 // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
1620 // in the WebCore MIMEType registry. For now we're doing this in a safe, limited manner
1621 // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
1622 if ([viewClass class] == [WebHTMLView class])
1623 MIMETypeRegistry::getSupportedNonImageMIMETypes().add(MIMEType);
1625 // This is used to make _representationExistsForURLScheme faster.
1626 // Without this set, we'd have to create the MIME type each time.
1627 if (schemesWithRepresentationsSet == nil) {
1628 schemesWithRepresentationsSet = [[NSMutableSet alloc] init];
1630 [schemesWithRepresentationsSet addObject:[[[URLScheme lowercaseString] copy] autorelease]];
1633 + (NSString *)_generatedMIMETypeForURLScheme:(NSString *)URLScheme
1635 return [@"x-apple-web-kit/" stringByAppendingString:[URLScheme lowercaseString]];
1638 + (BOOL)_representationExistsForURLScheme:(NSString *)URLScheme
1640 return [schemesWithRepresentationsSet containsObject:[URLScheme lowercaseString]];
1643 + (BOOL)_canHandleRequest:(NSURLRequest *)request forMainFrame:(BOOL)forMainFrame
1645 // FIXME: If <rdar://problem/5217309> gets fixed, this check can be removed.
1649 if ([NSURLConnection canHandleRequest:request])
1652 NSString *scheme = [[request URL] scheme];
1654 // Representations for URL schemes work at the top level.
1655 if (forMainFrame && [self _representationExistsForURLScheme:scheme])
1658 return [scheme _webkit_isCaseInsensitiveEqualToString:@"applewebdata"];
1661 + (BOOL)_canHandleRequest:(NSURLRequest *)request
1663 return [self _canHandleRequest:request forMainFrame:YES];
1666 + (NSString *)_decodeData:(NSData *)data
1668 HTMLNames::init(); // this method is used for importing bookmarks at startup, so HTMLNames are likely to be uninitialized yet
1669 RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("text/html"); // bookmark files are HTML
1670 String result = decoder->decode(static_cast<const char*>([data bytes]), [data length]);
1671 result += decoder->flush();
1675 - (void)_pushPerformingProgrammaticFocus
1677 _private->programmaticFocusCount++;
1680 - (void)_popPerformingProgrammaticFocus
1682 _private->programmaticFocusCount--;
1685 - (BOOL)_isPerformingProgrammaticFocus
1687 return _private->programmaticFocusCount != 0;
1690 - (void)_didChangeValueForKey: (NSString *)key
1692 LOG (Bindings, "calling didChangeValueForKey: %@", key);
1693 [self didChangeValueForKey: key];
1696 - (void)_willChangeValueForKey: (NSString *)key
1698 LOG (Bindings, "calling willChangeValueForKey: %@", key);
1699 [self willChangeValueForKey: key];
1702 + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key {
1703 static NSSet *manualNotifyKeys = nil;
1704 if (!manualNotifyKeys)
1705 manualNotifyKeys = [[NSSet alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey,
1706 _WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, _WebMainFrameDocumentKey,
1707 #if USE(ACCELERATED_COMPOSITING)
1708 UsingAcceleratedCompositingProperty, // used by DRT
1711 if ([manualNotifyKeys containsObject:key])
1716 - (NSArray *)_declaredKeys {
1717 static NSArray *declaredKeys = nil;
1719 declaredKeys = [[NSArray alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey,
1720 _WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, _WebMainFrameDocumentKey, nil];
1721 return declaredKeys;
1724 - (void)setObservationInfo:(void *)info
1726 _private->observationInfo = info;
1729 - (void *)observationInfo
1731 return _private->observationInfo;
1734 - (void)_willChangeBackForwardKeys
1736 [self _willChangeValueForKey: _WebCanGoBackKey];
1737 [self _willChangeValueForKey: _WebCanGoForwardKey];
1740 - (void)_didChangeBackForwardKeys
1742 [self _didChangeValueForKey: _WebCanGoBackKey];
1743 [self _didChangeValueForKey: _WebCanGoForwardKey];
1746 - (void)_didStartProvisionalLoadForFrame:(WebFrame *)frame
1748 [self _willChangeBackForwardKeys];
1749 if (frame == [self mainFrame]){
1750 // Force an observer update by sending a will/did.
1751 [self _willChangeValueForKey: _WebIsLoadingKey];
1752 [self _didChangeValueForKey: _WebIsLoadingKey];
1754 [self _willChangeValueForKey: _WebMainFrameURLKey];
1757 [NSApp setWindowsNeedUpdate:YES];
1760 - (void)_didCommitLoadForFrame:(WebFrame *)frame
1762 if (frame == [self mainFrame])
1763 [self _didChangeValueForKey: _WebMainFrameURLKey];
1764 [NSApp setWindowsNeedUpdate:YES];
1767 - (void)_didFinishLoadForFrame:(WebFrame *)frame
1769 [self _didChangeBackForwardKeys];
1770 if (frame == [self mainFrame]){
1771 // Force an observer update by sending a will/did.
1772 [self _willChangeValueForKey: _WebIsLoadingKey];
1773 [self _didChangeValueForKey: _WebIsLoadingKey];
1775 [NSApp setWindowsNeedUpdate:YES];
1778 - (void)_didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
1780 [self _didChangeBackForwardKeys];
1781 if (frame == [self mainFrame]){
1782 // Force an observer update by sending a will/did.
1783 [self _willChangeValueForKey: _WebIsLoadingKey];
1784 [self _didChangeValueForKey: _WebIsLoadingKey];
1786 [NSApp setWindowsNeedUpdate:YES];
1789 - (void)_didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
1791 [self _didChangeBackForwardKeys];
1792 if (frame == [self mainFrame]){
1793 // Force an observer update by sending a will/did.
1794 [self _willChangeValueForKey: _WebIsLoadingKey];
1795 [self _didChangeValueForKey: _WebIsLoadingKey];
1797 [self _didChangeValueForKey: _WebMainFrameURLKey];
1799 [NSApp setWindowsNeedUpdate:YES];
1802 - (NSCachedURLResponse *)_cachedResponseForURL:(NSURL *)URL
1804 NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:URL];
1805 [request _web_setHTTPUserAgent:[self userAgentForURL:URL]];
1806 NSCachedURLResponse *cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:request];
1808 return cachedResponse;
1811 - (void)_writeImageForElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
1813 NSURL *linkURL = [element objectForKey:WebElementLinkURLKey];
1814 DOMElement *domElement = [element objectForKey:WebElementDOMNodeKey];
1815 [pasteboard _web_writeImage:(NSImage *)(domElement ? nil : [element objectForKey:WebElementImageKey])
1817 URL:linkURL ? linkURL : (NSURL *)[element objectForKey:WebElementImageURLKey]
1818 title:[element objectForKey:WebElementImageAltStringKey]
1819 archive:[[element objectForKey:WebElementDOMNodeKey] webArchive]
1824 - (void)_writeLinkElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
1826 [pasteboard _web_writeURL:[element objectForKey:WebElementLinkURLKey]
1827 andTitle:[element objectForKey:WebElementLinkLabelKey]
1831 - (void)_setInitiatedDrag:(BOOL)initiatedDrag
1833 if (!_private->page)
1835 _private->page->dragController()->setDidInitiateDrag(initiatedDrag);
1838 #if ENABLE(DASHBOARD_SUPPORT)
1840 #define DASHBOARD_CONTROL_LABEL @"control"
1842 - (void)_addControlRect:(NSRect)bounds clip:(NSRect)clip fromView:(NSView *)view toDashboardRegions:(NSMutableDictionary *)regions
1844 NSRect adjustedBounds = bounds;
1845 adjustedBounds.origin = [self convertPoint:bounds.origin fromView:view];
1846 adjustedBounds.origin.y = [self bounds].size.height - adjustedBounds.origin.y;
1847 adjustedBounds.size = bounds.size;
1849 NSRect adjustedClip;
1850 adjustedClip.origin = [self convertPoint:clip.origin fromView:view];
1851 adjustedClip.origin.y = [self bounds].size.height - adjustedClip.origin.y;
1852 adjustedClip.size = clip.size;
1854 WebDashboardRegion *region = [[WebDashboardRegion alloc] initWithRect:adjustedBounds
1855 clip:adjustedClip type:WebDashboardRegionTypeScrollerRectangle];
1856 NSMutableArray *scrollerRegions = [regions objectForKey:DASHBOARD_CONTROL_LABEL];
1857 if (!scrollerRegions) {
1858 scrollerRegions = [[NSMutableArray alloc] init];
1859 [regions setObject:scrollerRegions forKey:DASHBOARD_CONTROL_LABEL];
1860 [scrollerRegions release];
1862 [scrollerRegions addObject:region];
1866 - (void)_addScrollerDashboardRegionsForFrameView:(FrameView*)frameView dashboardRegions:(NSMutableDictionary *)regions
1868 NSView *documentView = [[kit(frameView->frame()) frameView] documentView];
1870 const HashSet<Widget*>* children = frameView->children();
1871 HashSet<Widget*>::const_iterator end = children->end();
1872 for (HashSet<Widget*>::const_iterator it = children->begin(); it != end; ++it) {
1873 Widget* widget = *it;
1874 if (widget->isFrameView()) {
1875 [self _addScrollerDashboardRegionsForFrameView:static_cast<FrameView*>(widget) dashboardRegions:regions];
1879 if (!widget->isScrollbar())
1882 // FIXME: This should really pass an appropriate clip, but our first try got it wrong, and
1883 // it's not common to need this to be correct in Dashboard widgets.
1884 NSRect bounds = widget->frameRect();
1885 [self _addControlRect:bounds clip:bounds fromView:documentView toDashboardRegions:regions];
1889 - (void)_addScrollerDashboardRegions:(NSMutableDictionary *)regions from:(NSArray *)views
1891 // Add scroller regions for NSScroller and WebCore scrollbars
1892 NSUInteger count = [views count];
1893 for (NSUInteger i = 0; i < count; i++) {
1894 NSView *view = [views objectAtIndex:i];
1896 if ([view isKindOfClass:[WebHTMLView class]]) {
1897 if (Frame* coreFrame = core([(WebHTMLView*)view _frame])) {
1898 if (FrameView* coreView = coreFrame->view())
1899 [self _addScrollerDashboardRegionsForFrameView:coreView dashboardRegions:regions];
1901 } else if ([view isKindOfClass:[NSScroller class]]) {
1902 // AppKit places absent scrollers at -100,-100
1903 if ([view frame].origin.y < 0)
1905 [self _addControlRect:[view bounds] clip:[view visibleRect] fromView:view toDashboardRegions:regions];
1907 [self _addScrollerDashboardRegions:regions from:[view subviews]];
1911 - (void)_addScrollerDashboardRegions:(NSMutableDictionary *)regions
1913 [self _addScrollerDashboardRegions:regions from:[self subviews]];
1916 - (NSDictionary *)_dashboardRegions
1918 // Only return regions from main frame.
1919 Frame* mainFrame = core([self mainFrame]);
1922 NSMutableDictionary *regions = mainFrame->dashboardRegionsDictionary();
1923 [self _addScrollerDashboardRegions:regions];
1927 - (void)_setDashboardBehavior:(WebDashboardBehavior)behavior to:(BOOL)flag
1929 // FIXME: Remove this blanket assignment once Dashboard and Dashcode implement
1930 // specific support for the backward compatibility mode flag.
1931 if (behavior == WebDashboardBehaviorAllowWheelScrolling && flag == NO && _private->page)
1932 _private->page->settings()->setUsesDashboardBackwardCompatibilityMode(true);
1935 case WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows: {
1936 _private->dashboardBehaviorAlwaysSendMouseEventsToAllWindows = flag;
1939 case WebDashboardBehaviorAlwaysSendActiveNullEventsToPlugIns: {
1940 _private->dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns = flag;
1943 case WebDashboardBehaviorAlwaysAcceptsFirstMouse: {
1944 _private->dashboardBehaviorAlwaysAcceptsFirstMouse = flag;
1947 case WebDashboardBehaviorAllowWheelScrolling: {
1948 _private->dashboardBehaviorAllowWheelScrolling = flag;
1951 case WebDashboardBehaviorUseBackwardCompatibilityMode: {
1953 _private->page->settings()->setUsesDashboardBackwardCompatibilityMode(flag);
1959 - (BOOL)_dashboardBehavior:(WebDashboardBehavior)behavior
1962 case WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows: {
1963 return _private->dashboardBehaviorAlwaysSendMouseEventsToAllWindows;
1965 case WebDashboardBehaviorAlwaysSendActiveNullEventsToPlugIns: {
1966 return _private->dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns;
1968 case WebDashboardBehaviorAlwaysAcceptsFirstMouse: {
1969 return _private->dashboardBehaviorAlwaysAcceptsFirstMouse;
1971 case WebDashboardBehaviorAllowWheelScrolling: {
1972 return _private->dashboardBehaviorAllowWheelScrolling;
1974 case WebDashboardBehaviorUseBackwardCompatibilityMode: {
1975 return _private->page && _private->page->settings()->usesDashboardBackwardCompatibilityMode();
1981 #endif /* ENABLE(DASHBOARD_SUPPORT) */
1983 + (void)_setShouldUseFontSmoothing:(BOOL)f
1985 WebCoreSetShouldUseFontSmoothing(f);
1988 + (BOOL)_shouldUseFontSmoothing
1990 return WebCoreShouldUseFontSmoothing();
1993 + (void)_setUsesTestModeFocusRingColor:(BOOL)f
1995 setUsesTestModeFocusRingColor(f);
1998 + (BOOL)_usesTestModeFocusRingColor
2000 return usesTestModeFocusRingColor();
2003 // This is only used by versions of Safari up to and including 3.0 and should be removed in a future release.
2004 + (NSString *)_minimumRequiredSafariBuildNumber
2009 - (void)setAlwaysShowVerticalScroller:(BOOL)flag
2011 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
2013 [scrollview setVerticalScrollingMode:ScrollbarAlwaysOn andLock:YES];
2015 [scrollview setVerticalScrollingModeLocked:NO];
2016 [scrollview setVerticalScrollingMode:ScrollbarAuto andLock:NO];
2020 - (BOOL)alwaysShowVerticalScroller
2022 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
2023 return [scrollview verticalScrollingModeLocked] && [scrollview verticalScrollingMode] == ScrollbarAlwaysOn;
2026 - (void)setAlwaysShowHorizontalScroller:(BOOL)flag
2028 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
2030 [scrollview setHorizontalScrollingMode:ScrollbarAlwaysOn andLock:YES];
2032 [scrollview setHorizontalScrollingModeLocked:NO];
2033 [scrollview setHorizontalScrollingMode:ScrollbarAuto andLock:NO];
2037 - (void)setProhibitsMainFrameScrolling:(BOOL)prohibits
2039 Frame* mainFrame = core([self mainFrame]);
2041 mainFrame->view()->setProhibitsScrolling(prohibits);
2044 - (BOOL)alwaysShowHorizontalScroller
2046 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
2047 return [scrollview horizontalScrollingModeLocked] && [scrollview horizontalScrollingMode] == ScrollbarAlwaysOn;
2050 - (void)_setInViewSourceMode:(BOOL)flag
2052 Frame* mainFrame = core([self mainFrame]);
2054 mainFrame->setInViewSourceMode(flag);
2057 - (BOOL)_inViewSourceMode
2059 Frame* mainFrame = core([self mainFrame]);
2060 return mainFrame && mainFrame->inViewSourceMode();
2063 - (void)_setUseFastImageScalingMode:(BOOL)flag
2065 if (_private->page && _private->page->inLowQualityImageInterpolationMode() != flag) {
2066 _private->page->setInLowQualityImageInterpolationMode(flag);
2067 [self setNeedsDisplay:YES];
2071 - (BOOL)_inFastImageScalingMode
2074 return _private->page->inLowQualityImageInterpolationMode();
2078 - (BOOL)_cookieEnabled
2081 return _private->page->cookieEnabled();
2085 - (void)_setCookieEnabled:(BOOL)enable
2088 _private->page->setCookieEnabled(enable);
2091 - (void)_setAdditionalWebPlugInPaths:(NSArray *)newPaths
2093 if (!_private->pluginDatabase)
2094 _private->pluginDatabase = [[WebPluginDatabase alloc] init];
2096 [_private->pluginDatabase setPlugInPaths:newPaths];
2097 [_private->pluginDatabase refresh];
2100 - (void)_attachScriptDebuggerToAllFrames
2102 for (Frame* frame = core([self mainFrame]); frame; frame = frame->tree()->traverseNext())
2103 [kit(frame) _attachScriptDebugger];
2106 - (void)_detachScriptDebuggerFromAllFrames
2108 for (Frame* frame = core([self mainFrame]); frame; frame = frame->tree()->traverseNext())
2109 [kit(frame) _detachScriptDebugger];
2112 - (void)setBackgroundColor:(NSColor *)backgroundColor
2114 if ([_private->backgroundColor isEqual:backgroundColor])
2117 id old = _private->backgroundColor;
2118 _private->backgroundColor = [backgroundColor retain];
2121 [[self mainFrame] _updateBackgroundAndUpdatesWhileOffscreen];
2124 - (NSColor *)backgroundColor
2126 return _private->backgroundColor;
2129 - (BOOL)defersCallbacks
2131 if (!_private->page)
2133 return _private->page->defersLoading();
2136 - (void)setDefersCallbacks:(BOOL)defer
2138 if (!_private->page)
2140 return _private->page->setDefersLoading(defer);
2143 // For backwards compatibility with the WebBackForwardList API, we honor both
2144 // a per-WebView and a per-preferences setting for whether to use the page cache.
2146 - (BOOL)usesPageCache
2148 return _private->usesPageCache && [[self preferences] usesPageCache];
2151 - (void)setUsesPageCache:(BOOL)usesPageCache
2153 _private->usesPageCache = usesPageCache;
2155 // Post a notification so the WebCore settings update.
2156 [[self preferences] _postPreferencesChangesNotification];
2159 - (WebHistoryItem *)_globalHistoryItem
2161 if (!_private->page)
2163 return kit(_private->page->globalHistoryItem());
2166 - (WebTextIterator *)textIteratorForRect:(NSRect)rect
2168 IntPoint rectStart(rect.origin.x, rect.origin.y);
2169 IntPoint rectEnd(rect.origin.x + rect.size.width, rect.origin.y + rect.size.height);
2171 Frame* coreFrame = core([self mainFrame]);
2175 VisibleSelection selectionInsideRect(coreFrame->visiblePositionForPoint(rectStart), coreFrame->visiblePositionForPoint(rectEnd));
2177 return [[[WebTextIterator alloc] initWithRange:kit(selectionInsideRect.toNormalizedRange().get())] autorelease];
2180 - (void)handleAuthenticationForResource:(id)identifier challenge:(NSURLAuthenticationChallenge *)challenge fromDataSource:(WebDataSource *)dataSource
2182 NSWindow *window = [self hostWindow] ? [self hostWindow] : [self window];
2183 [[WebPanelAuthenticationHandler sharedHandler] startAuthentication:challenge window:window];
2186 - (void)_clearUndoRedoOperations
2188 if (!_private->page)
2190 _private->page->clearUndoRedoOperations();
2193 - (void)_setCatchesDelegateExceptions:(BOOL)f
2195 _private->catchesDelegateExceptions = f;
2198 - (BOOL)_catchesDelegateExceptions
2200 return _private->catchesDelegateExceptions;
2203 - (void)_executeCoreCommandByName:(NSString *)name value:(NSString *)value
2205 Frame* coreFrame = core([self mainFrame]);
2208 coreFrame->editor()->command(name).execute(value);
2211 - (void)_setCustomHTMLTokenizerTimeDelay:(double)timeDelay
2213 if (!_private->page)
2215 return _private->page->setCustomHTMLTokenizerTimeDelay(timeDelay);
2218 - (void)_setCustomHTMLTokenizerChunkSize:(int)chunkSize
2220 if (!_private->page)
2222 return _private->page->setCustomHTMLTokenizerChunkSize(chunkSize);
2225 - (void)_clearMainFrameName
2227 _private->page->mainFrame()->tree()->clearName();
2230 - (void)setSelectTrailingWhitespaceEnabled:(BOOL)flag
2232 _private->selectTrailingWhitespaceEnabled = flag;
2234 [self setSmartInsertDeleteEnabled:false];
2237 - (BOOL)isSelectTrailingWhitespaceEnabled
2239 return _private->selectTrailingWhitespaceEnabled;
2242 - (void)setMemoryCacheDelegateCallsEnabled:(BOOL)enabled
2244 _private->page->setMemoryCacheClientCallsEnabled(enabled);
2247 - (BOOL)areMemoryCacheDelegateCallsEnabled
2249 return _private->page->areMemoryCacheClientCallsEnabled();
2252 - (void)_setJavaScriptURLsAreAllowed:(BOOL)areAllowed
2254 _private->page->setJavaScriptURLsAreAllowed(areAllowed);
2257 + (NSCursor *)_pointingHandCursor
2259 return handCursor().impl();
2262 #if USE(ACCELERATED_COMPOSITING)
2264 - (BOOL)_needsOneShotDrawingSynchronization
2266 return _private->needsOneShotDrawingSynchronization;
2269 - (void)_setNeedsOneShotDrawingSynchronization:(BOOL)needsSynchronization
2271 _private->needsOneShotDrawingSynchronization = needsSynchronization;
2274 - (void)_startedAcceleratedCompositingForFrame:(WebFrame*)webFrame
2276 BOOL entering = _private->acceleratedFramesCount == 0;
2278 [self willChangeValueForKey:UsingAcceleratedCompositingProperty];
2279 ++_private->acceleratedFramesCount;
2281 [self didChangeValueForKey:UsingAcceleratedCompositingProperty];
2284 - (void)_stoppedAcceleratedCompositingForFrame:(WebFrame*)webFrame
2286 BOOL leaving = _private->acceleratedFramesCount == 1;
2287 ASSERT(_private->acceleratedFramesCount > 0);
2290 [self willChangeValueForKey:UsingAcceleratedCompositingProperty];
2291 --_private->acceleratedFramesCount;
2293 [self didChangeValueForKey:UsingAcceleratedCompositingProperty];
2298 - (BOOL)_isUsingAcceleratedCompositing
2300 #if USE(ACCELERATED_COMPOSITING)
2301 return _private->acceleratedFramesCount > 0;
2307 - (NSPasteboard *)_insertionPasteboard
2309 return _private ? _private->insertionPasteboard : nil;
2314 @implementation _WebSafeForwarder
2316 // Used to send messages to delegates that implement informal protocols.
2318 - (id)initWithTarget:(id)t defaultTarget:(id)dt catchExceptions:(BOOL)c
2320 self = [super init];
2323 target = t; // Non retained.
2325 catchExceptions = c;
2329 - (void)forwardInvocation:(NSInvocation *)invocation
2331 if ([target respondsToSelector:[invocation selector]]) {
2332 if (catchExceptions) {
2334 [invocation invokeWithTarget:target];
2335 } @catch(id exception) {
2336 ReportDiscardedDelegateException([invocation selector], exception);
2339 [invocation invokeWithTarget:target];
2343 if ([defaultTarget respondsToSelector:[invocation selector]])
2344 [invocation invokeWithTarget:defaultTarget];
2346 // Do nothing quietly if method not implemented.
2349 - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
2351 return [defaultTarget methodSignatureForSelector:aSelector];
2356 @implementation WebView
2360 static BOOL initialized = NO;
2365 InitWebCoreSystemInterface();
2367 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_applicationWillTerminate) name:NSApplicationWillTerminateNotification object:NSApp];
2368 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:) name:WebPreferencesChangedNotification object:nil];
2369 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesRemovedNotification:) name:WebPreferencesRemovedNotification object:nil];
2372 + (void)_applicationWillTerminate
2374 applicationIsTerminating = YES;
2376 if (fastDocumentTeardownEnabled())
2377 [self closeAllWebViews];
2379 if (!pluginDatabaseClientCount)
2380 [WebPluginDatabase closeSharedDatabase];
2382 PageGroup::closeLocalStorage();
2385 + (BOOL)canShowMIMEType:(NSString *)MIMEType
2387 return [self _viewClass:nil andRepresentationClass:nil forMIMEType:MIMEType];
2390 - (WebBasePluginPackage *)_pluginForMIMEType:(NSString *)MIMEType
2392 WebBasePluginPackage *pluginPackage = [[WebPluginDatabase sharedDatabase] pluginForMIMEType:MIMEType];
2394 return pluginPackage;
2396 if (_private->pluginDatabase)
2397 return [_private->pluginDatabase pluginForMIMEType:MIMEType];
2402 - (WebBasePluginPackage *)_pluginForExtension:(NSString *)extension
2404 WebBasePluginPackage *pluginPackage = [[WebPluginDatabase sharedDatabase] pluginForExtension:extension];
2406 return pluginPackage;
2408 if (_private->pluginDatabase)
2409 return [_private->pluginDatabase pluginForExtension:extension];
2414 - (void)addPluginInstanceView:(NSView *)view
2416 if (!_private->pluginDatabase)
2417 _private->pluginDatabase = [[WebPluginDatabase alloc] init];
2418 [_private->pluginDatabase addPluginInstanceView:view];
2421 - (void)removePluginInstanceView:(NSView *)view
2423 if (_private->pluginDatabase)
2424 [_private->pluginDatabase removePluginInstanceView:view];
2427 - (void)removePluginInstanceViewsFor:(WebFrame*)webFrame
2429 if (_private->pluginDatabase)
2430 [_private->pluginDatabase removePluginInstanceViewsFor:webFrame];
2433 - (BOOL)_isMIMETypeRegisteredAsPlugin:(NSString *)MIMEType
2435 if ([[WebPluginDatabase sharedDatabase] isMIMETypeRegistered:MIMEType])
2438 if (_private->pluginDatabase && [_private->pluginDatabase isMIMETypeRegistered:MIMEType])
2444 + (BOOL)canShowMIMETypeAsHTML:(NSString *)MIMEType
2446 return [WebFrameView _canShowMIMETypeAsHTML:MIMEType];
2449 + (NSArray *)MIMETypesShownAsHTML
2451 NSMutableDictionary *viewTypes = [WebFrameView _viewTypesAllowImageTypeOmission:YES];
2452 NSEnumerator *enumerator = [viewTypes keyEnumerator];
2454 NSMutableArray *array = [[[NSMutableArray alloc] init] autorelease];
2456 while ((key = [enumerator nextObject])) {
2457 if ([viewTypes objectForKey:key] == [WebHTMLView class])
2458 [array addObject:key];
2464 + (void)setMIMETypesShownAsHTML:(NSArray *)MIMETypes
2466 NSDictionary *viewTypes = [[WebFrameView _viewTypesAllowImageTypeOmission:YES] copy];
2467 NSEnumerator *enumerator = [viewTypes keyEnumerator];
2469 while ((key = [enumerator nextObject])) {
2470 if ([viewTypes objectForKey:key] == [WebHTMLView class])
2471 [WebView _unregisterViewClassAndRepresentationClassForMIMEType:key];
2474 int i, count = [MIMETypes count];
2475 for (i = 0; i < count; i++) {
2476 [WebView registerViewClass:[WebHTMLView class]
2477 representationClass:[WebHTMLRepresentation class]
2478 forMIMEType:[MIMETypes objectAtIndex:i]];
2480 [viewTypes release];
2483 + (NSURL *)URLFromPasteboard:(NSPasteboard *)pasteboard
2485 return [pasteboard _web_bestURL];
2488 + (NSString *)URLTitleFromPasteboard:(NSPasteboard *)pasteboard
2490 return [pasteboard stringForType:WebURLNamePboardType];
2493 + (void)registerURLSchemeAsLocal:(NSString *)protocol
2495 FrameLoader::registerURLSchemeAsLocal(protocol);
2498 - (id)_initWithArguments:(NSDictionary *) arguments
2500 NSCoder *decoder = [arguments objectForKey:@"decoder"];
2502 self = [self initWithCoder:decoder];
2504 ASSERT([arguments objectForKey:@"frame"]);
2505 NSValue *frameValue = [arguments objectForKey:@"frame"];
2506 NSRect frame = (frameValue ? [frameValue rectValue] : NSZeroRect);
2507 NSString *frameName = [arguments objectForKey:@"frameName"];
2508 NSString *groupName = [arguments objectForKey:@"groupName"];
2509 self = [self initWithFrame:frame frameName:frameName groupName:groupName];
2515 static bool clientNeedsWebViewInitThreadWorkaround()
2517 if (WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_WEBVIEW_INIT_THREAD_WORKAROUND))
2520 NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
2523 if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.installer"])
2527 if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.Automator"])
2530 // Automator Runner.
2531 if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.AutomatorRunner"])
2534 // Automator workflows.
2535 if ([bundleIdentifier _webkit_hasCaseInsensitivePrefix:@"com.apple.Automator."])
2541 static bool needsWebViewInitThreadWorkaround()
2543 static bool isOldClient = clientNeedsWebViewInitThreadWorkaround();
2544 return isOldClient && !pthread_main_np();
2547 - (id)initWithFrame:(NSRect)f
2549 return [self initWithFrame:f frameName:nil groupName:nil];
2552 - (id)initWithFrame:(NSRect)f frameName:(NSString *)frameName groupName:(NSString *)groupName
2554 if (needsWebViewInitThreadWorkaround())
2555 return [[self _webkit_invokeOnMainThread] initWithFrame:f frameName:frameName groupName:groupName];
2557 WebCoreThreadViolationCheckRoundTwo();
2558 return [self _initWithFrame:f frameName:frameName groupName:groupName usesDocumentViews:YES];
2561 - (id)initWithCoder:(NSCoder *)decoder
2563 if (needsWebViewInitThreadWorkaround())
2564 return [[self _webkit_invokeOnMainThread] initWithCoder:decoder];
2566 WebCoreThreadViolationCheckRoundTwo();
2567 WebView *result = nil;
2570 NSString *frameName;
2571 NSString *groupName;
2572 WebPreferences *preferences;
2573 BOOL useBackForwardList = NO;
2574 BOOL allowsUndo = YES;
2576 result = [super initWithCoder:decoder];
2577 result->_private = [[WebViewPrivate alloc] init];
2579 // We don't want any of the archived subviews. The subviews will always
2580 // be created in _commonInitializationFrameName:groupName:.
2581 [[result subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
2583 if ([decoder allowsKeyedCoding]) {
2584 frameName = [decoder decodeObjectForKey:@"FrameName"];
2585 groupName = [decoder decodeObjectForKey:@"GroupName"];
2586 preferences = [decoder decodeObjectForKey:@"Preferences"];
2587 useBackForwardList = [decoder decodeBoolForKey:@"UseBackForwardList"];
2588 if ([decoder containsValueForKey:@"AllowsUndo"])
2589 allowsUndo = [decoder decodeBoolForKey:@"AllowsUndo"];
2592 [decoder decodeValueOfObjCType:@encode(int) at:&version];
2593 frameName = [decoder decodeObject];
2594 groupName = [decoder decodeObject];
2595 preferences = [decoder decodeObject];
2597 [decoder decodeValuesOfObjCTypes:"c", &useBackForwardList];
2598 // The allowsUndo field is no longer written out in encodeWithCoder, but since there are
2599 // version 3 NIBs that have this field encoded, we still need to read it in.
2601 [decoder decodeValuesOfObjCTypes:"c", &allowsUndo];
2604 if (![frameName isKindOfClass:[NSString class]])
2606 if (![groupName isKindOfClass:[NSString class]])
2608 if (![preferences isKindOfClass:[WebPreferences class]])
2611 LOG(Encoding, "FrameName = %@, GroupName = %@, useBackForwardList = %d\n", frameName, groupName, (int)useBackForwardList);
2612 [result _commonInitializationWithFrameName:frameName groupName:groupName usesDocumentViews:YES];
2613 [result page]->backForwardList()->setEnabled(useBackForwardList);
2614 result->_private->allowsUndo = allowsUndo;
2616 [result setPreferences:preferences];
2617 } @catch (NSException *localException) {
2625 - (void)encodeWithCoder:(NSCoder *)encoder
2627 // Set asside the subviews before we archive. We don't want to archive any subviews.
2628 // The subviews will always be created in _commonInitializationFrameName:groupName:.
2629 id originalSubviews = _subviews;
2632 [super encodeWithCoder:encoder];
2634 // Restore the subviews we set aside.
2635 _subviews = originalSubviews;
2637 BOOL useBackForwardList = _private->page && _private->page->backForwardList()->enabled();
2638 if ([encoder allowsKeyedCoding]) {
2639 [encoder encodeObject:[[self mainFrame] name] forKey:@"FrameName"];
2640 [encoder encodeObject:[self groupName] forKey:@"GroupName"];
2641 [encoder encodeObject:[self preferences] forKey:@"Preferences"];
2642 [encoder encodeBool:useBackForwardList forKey:@"UseBackForwardList"];
2643 [encoder encodeBool:_private->allowsUndo forKey:@"AllowsUndo"];
2645 int version = WebViewVersion;
2646 [encoder encodeValueOfObjCType:@encode(int) at:&version];
2647 [encoder encodeObject:[[self mainFrame] name]];
2648 [encoder encodeObject:[self groupName]];
2649 [encoder encodeObject:[self preferences]];
2650 [encoder encodeValuesOfObjCTypes:"c", &useBackForwardList];
2651 // DO NOT encode any new fields here, doing so will break older WebKit releases.
2654 LOG(Encoding, "FrameName = %@, GroupName = %@, useBackForwardList = %d\n", [[self mainFrame] name], [self groupName], (int)useBackForwardList);
2659 if (WebCoreObjCScheduleDeallocateOnMainThread([WebView class], self))
2662 // call close to ensure we tear-down completely
2663 // this maintains our old behavior for existing applications
2669 // [super dealloc] can end up dispatching against _private (3466082)
2677 ASSERT(_private->closed);
2686 // _close existed first, and some clients might be calling or overriding it, so call through.
2690 - (void)setShouldCloseWithWindow:(BOOL)close
2692 _private->shouldCloseWithWindow = close;
2695 - (BOOL)shouldCloseWithWindow
2697 return _private->shouldCloseWithWindow;
2700 - (void)removeSizeObservers
2702 // -removeSizeObservers can be called from -viewWillMoveToSuperview: below -[NSView initWithCoder:], before
2703 // we've had a chance to initialize _private
2704 if (_private && [self window]) {
2705 [[NSNotificationCenter defaultCenter] removeObserver:self
2706 name:NSViewFrameDidChangeNotification object:self];
2707 [[NSNotificationCenter defaultCenter] removeObserver:self
2708 name:NSViewBoundsDidChangeNotification object:self];
2712 - (void)addSizeObserversForWindow:(NSWindow *)window
2714 // -addSizeObservers can be called from -viewDidMoveToSuperview: below -[NSView initWithCoder:], before
2715 // we've had a chance to initialize _private
2716 if (_private && window) {
2717 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_boundsChanged)
2718 name:NSViewFrameDidChangeNotification object:self];
2719 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_boundsChanged)
2720 name:NSViewBoundsDidChangeNotification object:self];
2721 [self _boundsChanged];
2725 - (void)addWindowObserversForWindow:(NSWindow *)window
2727 if (!_private->useDocumentViews && window) {
2728 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowDidBecomeKey:)
2729 name:NSWindowDidBecomeKeyNotification object:nil];
2730 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowDidResignKey:)
2731 name:NSWindowDidResignKeyNotification object:nil];
2732 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillOrderOnScreen:)
2733 name:WKWindowWillOrderOnScreenNotification() object:window];
2737 - (void)removeWindowObservers
2739 NSWindow *window = [self window];
2740 if (!_private->useDocumentViews && window) {
2741 [[NSNotificationCenter defaultCenter] removeObserver:self
2742 name:NSWindowDidBecomeKeyNotification object:nil];
2743 [[NSNotificationCenter defaultCenter] removeObserver:self
2744 name:NSWindowDidResignKeyNotification object:nil];
2745 [[NSNotificationCenter defaultCenter] removeObserver:self
2746 name:WKWindowWillOrderOnScreenNotification() object:window];
2750 - (void)viewWillMoveToWindow:(NSWindow *)window
2752 // Don't do anything if the WebView isn't initialized.
2753 // This happens when decoding a WebView in a nib.
2754 // FIXME: What sets up the observer of NSWindowWillCloseNotification in this case?
2755 if (!_private || _private->closed)
2758 if ([self window] && [self window] != [self hostWindow])
2759 [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowWillCloseNotification object:[self window]];
2762 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillClose:) name:NSWindowWillCloseNotification object:window];
2764 // Ensure that we will receive the events that WebHTMLView (at least) needs.
2765 // The following are expensive enough that we don't want to call them over
2766 // and over, so do them when we move into a window.
2767 [window setAcceptsMouseMovedEvents:YES];
2768 WKSetNSWindowShouldPostEventNotifications(window, YES);
2770 _private->page->willMoveOffscreen();
2772 if (window != [self window]) {
2773 [self removeSizeObservers];
2774 [self removeWindowObservers];
2776 [self addSizeObserversForWindow:window];
2777 [self addWindowObserversForWindow:window];
2781 - (void)viewDidMoveToWindow
2783 // Don't do anything if we aren't initialized. This happens
2784 // when decoding a WebView. When WebViews are decoded their subviews
2785 // are created by initWithCoder: and so won't be normally
2786 // initialized. The stub views are discarded by WebView.
2787 if (!_private || _private->closed)
2791 _private->page->didMoveOnscreen();
2794 - (void)_updateFocusedAndActiveState
2796 ASSERT(!_private->useDocumentViews);
2797 [self _updateFocusedAndActiveStateForFrame:[self mainFrame]];
2800 - (void)_updateFocusedAndActiveStateForFrame:(WebFrame *)webFrame
2802 Frame* frame = core(webFrame);
2806 Page* page = frame->page();
2810 NSWindow *window = [self window];
2811 BOOL windowIsKey = [window isKeyWindow];
2812 BOOL windowOrSheetIsKey = windowIsKey || [[window attachedSheet] isKeyWindow];
2814 WebFrameView *mainFrameView = [[self mainFrame] frameView];
2815 id <WebDocumentView> documentView = [mainFrameView documentView];
2816 BOOL documentViewIsResigningFirstResponder = [documentView isKindOfClass:[WebHTMLView class]] && [(WebHTMLView *)documentView _isResigningFirstResponder];
2818 NSResponder *firstResponder = [window firstResponder];
2819 if ([firstResponder isKindOfClass:[NSView class]]
2820 && [(NSView *)firstResponder isDescendantOf:mainFrameView])
2821 page->focusController()->setActive(windowIsKey && !documentViewIsResigningFirstResponder);
2823 Frame* focusedFrame = page->focusController()->focusedOrMainFrame();
2824 frame->selection()->setFocused(frame == focusedFrame && windowOrSheetIsKey);
2827 - (void)_windowDidBecomeKey:(NSNotification *)notification
2829 ASSERT(!_private->useDocumentViews);
2830 NSWindow *keyWindow = [notification object];
2831 if (keyWindow == [self window] || keyWindow == [[self window] attachedSheet])
2832 [self _updateFocusedAndActiveState];
2835 - (void)_windowDidResignKey:(NSNotification *)notification
2837 ASSERT(!_private->useDocumentViews);
2838 NSWindow *formerKeyWindow = [notification object];
2839 if (formerKeyWindow == [self window] || formerKeyWindow == [[self window] attachedSheet])
2840 [self _updateFocusedAndActiveState];
2843 - (void)_windowWillOrderOnScreen:(NSNotification *)notification
2845 ASSERT(!_private->useDocumentViews);
2846 if (![self shouldUpdateWhileOffscreen])
2847 [self setNeedsDisplay:YES];
2850 - (void)_windowWillClose:(NSNotification *)notification
2852 if ([self shouldCloseWithWindow] && ([self window] == [self hostWindow] || ([self window] && ![self hostWindow]) || (![self window] && [self hostWindow])))
2856 - (void)setPreferences:(WebPreferences *)prefs
2859 prefs = [WebPreferences standardPreferences];
2861 if (_private->preferences == prefs)
2864 [prefs willAddToWebView];
2866 WebPreferences *oldPrefs = _private->preferences;
2868 [[NSNotificationCenter defaultCenter] removeObserver:self name:WebPreferencesChangedNotification object:[self preferences]];
2869 [WebPreferences _removeReferenceForIdentifier:[oldPrefs identifier]];
2871 _private->preferences = [prefs retain];
2873 // After registering for the notification, post it so the WebCore settings update.
2874 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:)
2875 name:WebPreferencesChangedNotification object:[self preferences]];
2876 [[self preferences] _postPreferencesChangesNotification];
2878 [oldPrefs didRemoveFromWebView];
2882 - (WebPreferences *)preferences
2884 return _private->preferences;
2887 - (void)setPreferencesIdentifier:(NSString *)anIdentifier
2889 if (!_private->closed && ![anIdentifier isEqual:[[self preferences] identifier]]) {
2890 WebPreferences *prefs = [[WebPreferences alloc] initWithIdentifier:anIdentifier];
2891 [self setPreferences:prefs];
2896 - (NSString *)preferencesIdentifier
2898 return [[self preferences] identifier];
2902 - (void)setUIDelegate:delegate
2904 _private->UIDelegate = delegate;
2905 [_private->UIDelegateForwarder release];
2906 _private->UIDelegateForwarder = nil;
2911 return _private->UIDelegate;
2914 - (void)setResourceLoadDelegate: delegate
2916 _private->resourceProgressDelegate = delegate;
2917 [self _cacheResourceLoadDelegateImplementations];
2920 - resourceLoadDelegate
2922 return _private->resourceProgressDelegate;
2925 - (void)setDownloadDelegate: delegate
2927 _private->downloadDelegate = delegate;
2933 return _private->downloadDelegate;
2936 - (void)setPolicyDelegate:delegate
2938 _private->policyDelegate = delegate;
2939 [_private->policyDelegateForwarder release];
2940 _private->policyDelegateForwarder = nil;
2945 return _private->policyDelegate;
2948 - (void)setFrameLoadDelegate:delegate
2950 _private->frameLoadDelegate = delegate;
2951 [self _cacheFrameLoadDelegateImplementations];
2953 // If this delegate wants callbacks for icons, fire up the icon database.
2954 if (_private->frameLoadDelegateImplementations.didReceiveIconForFrameFunc)
2955 [WebIconDatabase sharedIconDatabase];
2960 return _private->frameLoadDelegate;
2963 - (WebFrame *)mainFrame
2965 // This can be called in initialization, before _private has been set up (3465613)
2968 if (!_private->page)
2970 return kit(_private->page->mainFrame());
2973 - (WebFrame *)selectedFrame
2975 // If the first responder is a view in our tree, we get the frame containing the first responder.
2976 // This is faster than searching the frame hierarchy, and will give us a result even in the case
2977 // where the focused frame doesn't actually contain a selection.
2978 WebFrame *focusedFrame = [self _focusedFrame];
2980 return focusedFrame;
2982 // If the first responder is outside of our view tree, we search for a frame containing a selection.
2983 // There should be at most only one of these.
2984 return [[self mainFrame] _findFrameWithSelection];
2987 - (WebBackForwardList *)backForwardList
2989 if (!_private->page)
2991 if (!_private->page->backForwardList()->enabled())
2993 return kit(_private->page->backForwardList());
2996 - (void)setMaintainsBackForwardList: (BOOL)flag
2998 if (!_private->page)
3000 _private->page->backForwardList()->setEnabled(flag);
3005 if (!_private->page)
3008 return _private->page->goBack();
3013 if (!_private->page)
3016 return _private->page->goForward();
3019 - (BOOL)goToBackForwardItem:(WebHistoryItem *)item
3021 if (!_private->page)
3024 _private->page->goToItem(core(item), FrameLoadTypeIndexedBackForward);
3028 - (void)setTextSizeMultiplier:(float)m
3030 [self _setZoomMultiplier:m isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3033 - (float)textSizeMultiplier
3035 return [self _realZoomMultiplierIsTextOnly] ? _private->zoomMultiplier : 1.0f;
3038 - (void)_setZoomMultiplier:(float)m isTextOnly:(BOOL)isTextOnly
3040 // NOTE: This has no visible effect when viewing a PDF (see <rdar://problem/4737380>)
3041 _private->zoomMultiplier = m;
3042 ASSERT(_private->page);
3044 _private->page->settings()->setZoomsTextOnly(isTextOnly);
3046 // FIXME: it would be nice to rework this code so that _private->zoomMultiplier doesn't exist and callers
3047 // all access _private->page->settings().
3048 Frame* coreFrame = core([self mainFrame]);
3050 coreFrame->setZoomFactor(m, isTextOnly);
3053 - (float)_zoomMultiplier:(BOOL)isTextOnly
3055 if (isTextOnly != [self _realZoomMultiplierIsTextOnly])
3057 return _private->zoomMultiplier;
3060 - (float)_realZoomMultiplier
3062 return _private->zoomMultiplier;
3065 - (BOOL)_realZoomMultiplierIsTextOnly
3067 if (!_private->page)
3070 return _private->page->settings()->zoomsTextOnly();
3073 #define MinimumZoomMultiplier 0.5f
3074 #define MaximumZoomMultiplier 3.0f
3075 #define ZoomMultiplierRatio 1.2f
3077 - (BOOL)_canZoomOut:(BOOL)isTextOnly
3079 id docView = [[[self mainFrame] frameView] documentView];
3080 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
3081 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
3082 return [zoomingDocView _canZoomOut];
3084 return [self _zoomMultiplier:isTextOnly] / ZoomMultiplierRatio > MinimumZoomMultiplier;
3088 - (BOOL)_canZoomIn:(BOOL)isTextOnly
3090 id docView = [[[self mainFrame] frameView] documentView];
3091 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
3092 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
3093 return [zoomingDocView _canZoomIn];
3095 return [self _zoomMultiplier:isTextOnly] * ZoomMultiplierRatio < MaximumZoomMultiplier;
3098 - (IBAction)_zoomOut:(id)sender isTextOnly:(BOOL)isTextOnly
3100 id docView = [[[self mainFrame] frameView] documentView];
3101 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
3102 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
3103 return [zoomingDocView _zoomOut:sender];
3105 float newScale = [self _zoomMultiplier:isTextOnly] / ZoomMultiplierRatio;
3106 if (newScale > MinimumZoomMultiplier)
3107 [self _setZoomMultiplier:newScale isTextOnly:isTextOnly];
3110 - (IBAction)_zoomIn:(id)sender isTextOnly:(BOOL)isTextOnly
3112 id docView = [[[self mainFrame] frameView] documentView];
3113 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
3114 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
3115 return [zoomingDocView _zoomIn:sender];
3117 float newScale = [self _zoomMultiplier:isTextOnly] * ZoomMultiplierRatio;
3118 if (newScale < MaximumZoomMultiplier)
3119 [self _setZoomMultiplier:newScale isTextOnly:isTextOnly];
3122 - (BOOL)_canResetZoom:(BOOL)isTextOnly
3124 id docView = [[[self mainFrame] frameView] documentView];
3125 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
3126 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
3127 return [zoomingDocView _canResetZoom];
3129 return [self _zoomMultiplier:isTextOnly] != 1.0f;
3132 - (IBAction)_resetZoom:(id)sender isTextOnly:(BOOL)isTextOnly
3134 id docView = [[[self mainFrame] frameView] documentView];
3135 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
3136 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
3137 return [zoomingDocView _resetZoom:sender];
3139 if ([self _zoomMultiplier:isTextOnly] != 1.0f)
3140 [self _setZoomMultiplier:1.0f isTextOnly:isTextOnly];
3143 - (void)viewWillMoveToSuperview:(NSView *)newSuperview
3145 [self removeSizeObservers];
3148 - (void)viewDidMoveToSuperview
3150 if ([self superview] != nil)
3151 [self addSizeObserversForWindow:[self window]];
3154 - (void)setApplicationNameForUserAgent:(NSString *)applicationName
3156 NSString *name = [applicationName copy];
3157 [_private->applicationNameForUserAgent release];
3158 _private->applicationNameForUserAgent = name;
3159 if (!_private->userAgentOverridden)
3160 _private->userAgent = String();
3163 - (NSString *)applicationNameForUserAgent
3165 return [[_private->applicationNameForUserAgent retain] autorelease];
3168 - (void)setCustomUserAgent:(NSString *)userAgentString
3170 _private->userAgent = userAgentString;
3171 _private->userAgentOverridden = userAgentString != nil;
3174 - (NSString *)customUserAgent
3176 if (!_private->userAgentOverridden)
3178 return _private->userAgent;
3181 - (void)setMediaStyle:(NSString *)mediaStyle
3183 if (_private->mediaStyle != mediaStyle) {
3184 [_private->mediaStyle release];
3185 _private->mediaStyle = [mediaStyle copy];
3189 - (NSString *)mediaStyle
3191 return _private->mediaStyle;
3194 - (BOOL)supportsTextEncoding
3196 id documentView = [[[self mainFrame] frameView] documentView];
3197 return [documentView conformsToProtocol:@protocol(WebDocumentText)]
3198 && [documentView supportsTextEncoding];
3201 - (void)setCustomTextEncodingName:(NSString *)encoding
3203 NSString *oldEncoding = [self customTextEncodingName];
3204 if (encoding == oldEncoding || [encoding isEqualToString:oldEncoding])
3206 if (Frame* mainFrame = core([self mainFrame]))
3207 mainFrame->loader()->reloadWithOverrideEncoding(encoding);
3210 - (NSString *)_mainFrameOverrideEncoding
3212 WebDataSource *dataSource = [[self mainFrame] provisionalDataSource];
3213 if (dataSource == nil)
3214 dataSource = [[self mainFrame] _dataSource];
3215 if (dataSource == nil)
3217 return nsStringNilIfEmpty([dataSource _documentLoader]->overrideEncoding());
3220 - (NSString *)customTextEncodingName
3222 return [self _mainFrameOverrideEncoding];
3225 - (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script
3227 // Return statements are only valid in a function but some applications pass in scripts
3228 // prefixed with return (<rdar://problems/5103720&4616860>) since older WebKit versions
3229 // silently ignored the return. If the application is linked against an earlier version
3230 // of WebKit we will strip the return so the script wont fail.
3231 if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_JAVASCRIPT_RETURN_QUIRK)) {
3232 NSRange returnStringRange = [script rangeOfString:@"return "];
3233 if (returnStringRange.length && !returnStringRange.location)
3234 script = [script substringFromIndex:returnStringRange.location + returnStringRange.length];
3237 NSString *result = [[self mainFrame] _stringByEvaluatingJavaScriptFromString:script];
3238 // The only way stringByEvaluatingJavaScriptFromString can return nil is if the frame was removed by the script
3239 // Since there's no way to get rid of the main frame, result will never ever be nil here.
3245 - (WebScriptObject *)windowScriptObject
3247 Frame* coreFrame = core([self mainFrame]);
3250 return coreFrame->script()->windowScriptObject();
3253 // Get the appropriate user-agent string for a particular URL.
3254 - (NSString *)userAgentForURL:(NSURL *)url
3256 return [self _userAgentForURL:KURL([url absoluteURL])];
3259 - (void)setHostWindow:(NSWindow *)hostWindow
3261 if (_private->closed)
3263 if (hostWindow == _private->hostWindow)
3266 Frame* coreFrame = core([self mainFrame]);
3267 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
3268 [[[kit(frame) frameView] documentView] viewWillMoveToHostWindow:hostWindow];
3269 if (_private->hostWindow && [self window] != _private->hostWindow)
3270 [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowWillCloseNotification object:_private->hostWindow];
3272 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillClose:) name:NSWindowWillCloseNotification object:hostWindow];
3273 [_private->hostWindow release];
3274 _private->hostWindow = [hostWindow retain];
3275 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
3276 [[[kit(frame) frameView] documentView] viewDidMoveToHostWindow];
3279 - (NSWindow *)hostWindow
3281 // -[WebView hostWindow] can sometimes be called from the WebView's [super dealloc] method
3282 // so we check here to make sure it's not null.
3286 return _private->hostWindow;
3289 - (NSView <WebDocumentView> *)documentViewAtWindowPoint:(NSPoint)point
3291 return [[self _frameViewAtWindowPoint:point] documentView];
3294 - (NSDictionary *)_elementAtWindowPoint:(NSPoint)windowPoint
3296 WebFrameView *frameView = [self _frameViewAtWindowPoint:windowPoint];
3299 NSView <WebDocumentView> *documentView = [frameView documentView];
3300 if ([documentView conformsToProtocol:@protocol(WebDocumentElement)]) {
3301 NSPoint point = [documentView convertPoint:windowPoint fromView:nil];
3302 return [(NSView <WebDocumentElement> *)documentView elementAtPoint:point];
3304 return [NSDictionary dictionaryWithObject:[frameView webFrame] forKey:WebElementFrameKey];
3307 - (NSDictionary *)elementAtPoint:(NSPoint)point
3309 return [self _elementAtWindowPoint:[self convertPoint:point toView:nil]];
3312 // The following 2 internal NSView methods are called on the drag destination by make scrolling while dragging work.
3313 // Scrolling while dragging will only work if the drag destination is in a scroll view. The WebView is the drag destination.
3314 // When dragging to a WebView, the document subview should scroll, but it doesn't because it is not the drag destination.
3315 // Forward these calls to the document subview to make its scroll view scroll.
3316 - (void)_autoscrollForDraggingInfo:(id)draggingInfo timeDelta:(NSTimeInterval)repeatDelta
3318 NSView <WebDocumentView> *documentView = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3319 [documentView _autoscrollForDraggingInfo:draggingInfo timeDelta:repeatDelta];
3322 - (BOOL)_shouldAutoscrollForDraggingInfo:(id)draggingInfo
3324 NSView <WebDocumentView> *documentView = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3325 return [documentView _shouldAutoscrollForDraggingInfo:draggingInfo];
3328 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)draggingInfo
3330 NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3331 WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]] ? (WebHTMLView*)view : nil);
3332 IntPoint client([draggingInfo draggingLocation]);
3333 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
3334 DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
3335 return core(self)->dragController()->dragEntered(&dragData);
3338 - (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)draggingInfo
3340 Page* page = core(self);
3342 return NSDragOperationNone;
3344 NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3345 WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]] ? (WebHTMLView*)view : nil);
3346 IntPoint client([draggingInfo draggingLocation]);
3347 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
3348 DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
3349 return page->dragController()->dragUpdated(&dragData);
3352 - (void)draggingExited:(id <NSDraggingInfo>)draggingInfo
3354 Page* page = core(self);
3358 NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3359 WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]] ? (WebHTMLView*)view : nil);
3360 IntPoint client([draggingInfo draggingLocation]);
3361 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
3362 DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
3363 page->dragController()->dragExited(&dragData);
3366 - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)draggingInfo
3371 - (BOOL)performDragOperation:(id <NSDraggingInfo>)draggingInfo
3373 NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3374 WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]]? (WebHTMLView*)view : nil);
3375 IntPoint client([draggingInfo draggingLocation]);
3376 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
3377 DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
3378 return core(self)->dragController()->performDrag(&dragData);
3381 - (NSView *)_hitTest:(NSPoint *)aPoint dragTypes:(NSSet *)types
3383 NSView *hitView = [super _hitTest:aPoint dragTypes:types];
3384 if (!hitView && [[self superview] mouse:*aPoint inRect:[self frame]]) {
3391 - (BOOL)acceptsFirstResponder
3393 return [[[self mainFrame] frameView] acceptsFirstResponder];
3396 - (BOOL)becomeFirstResponder
3398 if (_private->becomingFirstResponder) {
3399 // Fix for unrepro infinite recursion reported in radar 4448181. If we hit this assert on
3400 // a debug build, we should figure out what causes the problem and do a better fix.
3401 ASSERT_NOT_REACHED();
3405 // This works together with setNextKeyView to splice the WebView into
3406 // the key loop similar to the way NSScrollView does this. Note that
3407 // WebFrameView has very similar code.
3408 NSWindow *window = [self window];
3409 WebFrameView *mainFrameView = [[self mainFrame] frameView];
3411 NSResponder *previousFirstResponder = [[self window] _oldFirstResponderBeforeBecoming];
3412 BOOL fromOutside = ![previousFirstResponder isKindOfClass:[NSView class]] || (![(NSView *)previousFirstResponder isDescendantOf:self] && previousFirstResponder != self);
3414 if ([window keyViewSelectionDirection] == NSSelectingPrevious) {
3415 NSView *previousValidKeyView = [self previousValidKeyView];
3416 if ((previousValidKeyView != self) && (previousValidKeyView != mainFrameView)) {
3417 _private->becomingFirstResponder = YES;
3418 _private->becomingFirstResponderFromOutside = fromOutside;
3419 [window makeFirstResponder:previousValidKeyView];
3420 _private->becomingFirstResponderFromOutside = NO;
3421 _private->becomingFirstResponder = NO;
3428 if ([mainFrameView acceptsFirstResponder]) {
3429 _private->becomingFirstResponder = YES;
3430 _private->becomingFirstResponderFromOutside = fromOutside;
3431 [window makeFirstResponder:mainFrameView];
3432 _private->becomingFirstResponderFromOutside = NO;
3433 _private->becomingFirstResponder = NO;
3440 - (NSView *)_webcore_effectiveFirstResponder
3442 WebFrameView *frameView = [[self mainFrame] frameView];
3443 return frameView ? [frameView _webcore_effectiveFirstResponder] : [super _webcore_effectiveFirstResponder];
3446 - (void)setNextKeyView:(NSView *)aView
3448 // This works together with becomeFirstResponder to splice the WebView into
3449 // the key loop similar to the way NSScrollView does this. Note that
3450 // WebFrameView has very similar code.
3451 WebFrameView *mainFrameView = [[self mainFrame] frameView];
3452 if (mainFrameView != nil) {
3453 [mainFrameView setNextKeyView:aView];
3455 [super setNextKeyView:aView];
3459 static WebFrame *incrementFrame(WebFrame *curr, BOOL forward, BOOL wrapFlag)
3461 Frame* coreFrame = core(curr);
3463 ? coreFrame->tree()->traverseNextWithWrap(wrapFlag)
3464 : coreFrame->tree()->traversePreviousWithWrap(wrapFlag));
3467 - (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag
3469 return [self searchFor:string direction:forward caseSensitive:caseFlag wrap:wrapFlag startInSelection:NO];
3472 + (void)registerViewClass:(Class)viewClass representationClass:(Class)representationClass forMIMEType:(NSString *)MIMEType
3474 [[WebFrameView _viewTypesAllowImageTypeOmission:YES] setObject:viewClass forKey:MIMEType];
3475 [[WebDataSource _repTypesAllowImageTypeOmission:YES] setObject:representationClass forKey:MIMEType];
3477 // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
3478 // in the WebCore MIMEType registry. For now we're doing this in a safe, limited manner
3479 // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
3480 if ([viewClass class] == [WebHTMLView class])
3481 MIMETypeRegistry::getSupportedNonImageMIMETypes().add(MIMEType);
3484 - (void)setGroupName:(NSString *)groupName
3486 if (!_private->page)
3488 _private->page->setGroupName(groupName);
3491 - (NSString *)groupName
3493 if (!_private->page)
3495 return _private->page->groupName();
3498 - (double)estimatedProgress
3500 if (!_private->page)
3503 return _private->page->progress()->estimatedProgress();
3506 - (NSArray *)pasteboardTypesForSelection
3508 NSView <WebDocumentView> *documentView = [[[self _selectedOrMainFrame] frameView] documentView];
3509 if ([documentView conformsToProtocol:@protocol(WebDocumentSelection)]) {
3510 return [(NSView <WebDocumentSelection> *)documentView pasteboardTypesForSelection];
3512 return [NSArray array];
3515 - (void)writeSelectionWithPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
3517 WebFrame *frame = [self _selectedOrMainFrame];
3518 if (frame && [frame _hasSelection]) {
3519 NSView <WebDocumentView> *documentView = [[frame frameView] documentView];
3520 if ([documentView conformsToProtocol:@protocol(WebDocumentSelection)])
3521 [(NSView <WebDocumentSelection> *)documentView writeSelectionWithPasteboardTypes:types toPasteboard:pasteboard];
3525 - (NSArray *)pasteboardTypesForElement:(NSDictionary *)element
3527 if ([element objectForKey:WebElementImageURLKey] != nil) {
3528 return [NSPasteboard _web_writableTypesForImageIncludingArchive:([element objectForKey:WebElementDOMNodeKey] != nil)];
3529 } else if ([element objectForKey:WebElementLinkURLKey] != nil) {
3530 return [NSPasteboard _web_writableTypesForURL];
3531 } else if ([[element objectForKey:WebElementIsSelectedKey] boolValue]) {
3532 return [self pasteboardTypesForSelection];
3534 return [NSArray array];
3537 - (void)writeElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
3539 if ([element objectForKey:WebElementImageURLKey] != nil) {
3540 [self _writeImageForElement:element withPasteboardTypes:types toPasteboard:pasteboard];
3541 } else if ([element objectForKey:WebElementLinkURLKey] != nil) {
3542 [self _writeLinkElement:element withPasteboardTypes:types toPasteboard:pasteboard];
3543 } else if ([[element objectForKey:WebElementIsSelectedKey] boolValue]) {
3544 [self writeSelectionWithPasteboardTypes:types toPasteboard:pasteboard];
3548 - (void)moveDragCaretToPoint:(NSPoint)point
3550 if (Page* page = core(self))
3551 page->dragController()->placeDragCaret(IntPoint([self convertPoint:point toView:nil]));
3554 - (void)removeDragCaret
3556 if (Page* page = core(self))
3557 page->dragController()->dragEnded();
3560 - (void)setMainFrameURL:(NSString *)URLString
3562 [[self mainFrame] loadRequest: [NSURLRequest requestWithURL: [NSURL _web_URLWithDataAsString: URLString]]];
3565 - (NSString *)mainFrameURL
3568 ds = [[self mainFrame] provisionalDataSource];
3570 ds = [[self mainFrame] _dataSource];
3571 return [[[ds request] URL] _web_originalDataAsString];
3576 LOG (Bindings, "isLoading = %d", (int)[self _isLoading]);
3577 return [self _isLoading];
3580 - (NSString *)mainFrameTitle
3582 NSString *mainFrameTitle = [[[self mainFrame] _dataSource] pageTitle];
3583 return (mainFrameTitle != nil) ? mainFrameTitle : (NSString *)@"";
3586 - (NSImage *)mainFrameIcon
3588 return [[WebIconDatabase sharedIconDatabase] iconForURL:[[[[self mainFrame] _dataSource] _URL] _web_originalDataAsString] withSize:WebIconSmallSize];
3591 - (DOMDocument *)mainFrameDocument
3593 // only return the actual value if the state we're in gives NSTreeController
3594 // enough time to release its observers on the old model
3595 if (_private->mainFrameDocumentReady)
3596 return [[self mainFrame] DOMDocument];
3600 - (void)setDrawsBackground:(BOOL)drawsBackground
3602 if (_private->drawsBackground == drawsBackground)
3604 _private->drawsBackground = drawsBackground;
3605 [[self mainFrame] _updateBackgroundAndUpdatesWhileOffscreen];
3608 - (BOOL)drawsBackground
3610 // This method can be called beneath -[NSView dealloc] after we have cleared _private,
3611 // indirectly via -[WebFrameView viewDidMoveToWindow].
3612 return !_private || _private->drawsBackground;
3615 - (void)setShouldUpdateWhileOffscreen:(BOOL)updateWhileOffscreen
3617 if (_private->shouldUpdateWhileOffscreen == updateWhileOffscreen)
3619 _private->shouldUpdateWhileOffscreen = updateWhileOffscreen;
3620 [[self mainFrame] _updateBackgroundAndUpdatesWhileOffscreen];
3623 - (BOOL)shouldUpdateWhileOffscreen
3625 return _private->shouldUpdateWhileOffscreen;
3628 - (void)setCurrentNodeHighlight:(WebNodeHighlight *)nodeHighlight
3630 id old = _private->currentNodeHighlight;
3631 _private->currentNodeHighlight = [nodeHighlight retain];
3635 - (WebNodeHighlight *)currentNodeHighlight
3637 return _private->currentNodeHighlight;
3642 @implementation WebView (WebIBActions)
3644 - (IBAction)takeStringURLFrom: sender
3646 NSString *URLString = [sender stringValue];
3648 [[self mainFrame] loadRequest: [NSURLRequest requestWithURL: [NSURL _web_URLWithDataAsString: URLString]]];
3653 if (!_private->page)
3656 return !!_private->page->backForwardList()->backItem();
3659 - (BOOL)canGoForward
3661 if (!_private->page)
3664 return !!_private->page->backForwardList()->forwardItem();
3667 - (IBAction)goBack:(id)sender
3672 - (IBAction)goForward:(id)sender
3677 - (IBAction)stopLoading:(id)sender
3679 [[self mainFrame] stopLoading];
3682 - (IBAction)reload:(id)sender
3684 [[self mainFrame] reload];
3687 - (IBAction)reloadFromOrigin:(id)sender
3689 [[self mainFrame] reloadFromOrigin];
3692 // FIXME: This code should move into WebCore so that it is not duplicated in each WebKit.
3693 // (This includes canMakeTextSmaller/Larger, makeTextSmaller/Larger, and canMakeTextStandardSize/makeTextStandardSize)
3694 - (BOOL)canMakeTextSmaller
3696 return [self _canZoomOut:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3699 - (IBAction)makeTextSmaller:(id)sender
3701 return [self _zoomOut:sender isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3704 - (BOOL)canMakeTextLarger
3706 return [self _canZoomIn:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3709 - (IBAction)makeTextLarger:(id)sender
3711 return [self _zoomIn:sender isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3714 - (BOOL)canMakeTextStandardSize
3716 return [self _canResetZoom:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3719 - (IBAction)makeTextStandardSize:(id)sender
3721 return [self _resetZoom:sender isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3724 - (IBAction)toggleSmartInsertDelete:(id)sender
3726 [self setSmartInsertDeleteEnabled:![self smartInsertDeleteEnabled]];
3729 - (IBAction)toggleContinuousSpellChecking:(id)sender
3731 [self setContinuousSpellCheckingEnabled:![self isContinuousSpellCheckingEnabled]];
3734 - (BOOL)_responderValidateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item
3736 id responder = [self _responderForResponderOperations];
3737 if (responder != self && [responder respondsToSelector:[item action]]) {
3738 if ([responder respondsToSelector:@selector(validateUserInterfaceItemWithoutDelegate:)])
3739 return [responder validateUserInterfaceItemWithoutDelegate:item];
3740 if ([responder respondsToSelector:@selector(validateUserInterfaceItem:)])
3741 return [responder validateUserInterfaceItem:item];
3747 #define VALIDATE(name) \
3748 else if (action == @selector(name:)) { return [self _responderValidateUserInterfaceItem:item]; }
3750 - (BOOL)validateUserInterfaceItemWithoutDelegate:(id <NSValidatedUserInterfaceItem>)item
3752 SEL action = [item action];
3754 if (action == @selector(goBack:)) {
3755 return [self canGoBack];
3756 } else if (action == @selector(goForward:)) {
3757 return [self canGoForward];
3758 } else if (action == @selector(makeTextLarger:)) {
3759 return [self canMakeTextLarger];
3760 } else if (action == @selector(makeTextSmaller:)) {
3761 return [self canMakeTextSmaller];
3762 } else if (action == @selector(makeTextStandardSize:)) {
3763 return [self canMakeTextStandardSize];
3764 } else if (action == @selector(reload:)) {
3765 return [[self mainFrame] _dataSource] != nil;
3766 } else if (action == @selector(stopLoading:)) {
3767 return [self _isLoading];
3768 } else if (action == @selector(toggleContinuousSpellChecking:)) {
3769 BOOL checkMark = NO;
3771 if ([self _continuousCheckingAllowed]) {
3772 checkMark = [self isContinuousSpellCheckingEnabled];
3775 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
3776 NSMenuItem *menuItem = (NSMenuItem *)item;
3777 [menuItem setState:checkMark ? NSOnState : NSOffState];
3780 } else if (action == @selector(toggleSmartInsertDelete:)) {
3781 BOOL checkMark = [self smartInsertDeleteEnabled];
3782 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
3783 NSMenuItem *menuItem = (NSMenuItem *)item;
3784 [menuItem setState:checkMark ? NSOnState : NSOffState];
3787 #ifndef BUILDING_ON_TIGER
3788 } else if (action == @selector(toggleGrammarChecking:)) {
3789 BOOL checkMark = [self isGrammarCheckingEnabled];
3790 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
3791 NSMenuItem *menuItem = (NSMenuItem *)item;
3792 [menuItem setState:checkMark ? NSOnState : NSOffState];