2 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
3 * Copyright (C) 2006 David Smith (catfish.man@gmail.com)
4 * Copyright (C) 2010 Igalia S.L
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
16 * its contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #import "WebViewInternal.h"
32 #import "WebViewData.h"
34 #import "DOMCSSStyleDeclarationInternal.h"
35 #import "DOMNodeInternal.h"
36 #import "DOMRangeInternal.h"
37 #import "WebApplicationCache.h"
38 #import "WebBackForwardListInternal.h"
39 #import "WebBaseNetscapePluginView.h"
41 #import "WebChromeClient.h"
42 #import "WebContextMenuClient.h"
43 #import "WebDOMOperationsPrivate.h"
44 #import "WebDataSourceInternal.h"
45 #import "WebDatabaseManagerInternal.h"
46 #import "WebDefaultEditingDelegate.h"
47 #import "WebDefaultPolicyDelegate.h"
48 #import "WebDefaultUIDelegate.h"
49 #import "WebDelegateImplementationCaching.h"
50 #import "WebDeviceOrientationClient.h"
51 #import "WebDeviceOrientationProvider.h"
52 #import "WebDocument.h"
53 #import "WebDocumentInternal.h"
54 #import "WebDownload.h"
55 #import "WebDownloadInternal.h"
56 #import "WebDragClient.h"
57 #import "WebDynamicScrollBarsViewInternal.h"
58 #import "WebEditingDelegate.h"
59 #import "WebEditorClient.h"
60 #import "WebFormDelegatePrivate.h"
61 #import "WebFrameInternal.h"
62 #import "WebFrameViewInternal.h"
63 #import "WebGeolocationControllerClient.h"
64 #import "WebGeolocationPositionInternal.h"
65 #import "WebHTMLRepresentation.h"
66 #import "WebHTMLViewInternal.h"
67 #import "WebHistoryItemInternal.h"
68 #import "WebIconDatabaseInternal.h"
69 #import "WebInspector.h"
70 #import "WebInspectorClient.h"
71 #import "WebKitErrors.h"
72 #import "WebKitLogging.h"
73 #import "WebKitNSStringExtras.h"
74 #import "WebKitStatisticsPrivate.h"
75 #import "WebKitSystemBits.h"
76 #import "WebKitVersionChecks.h"
77 #import "WebLocalizableStrings.h"
78 #import "WebNSDataExtras.h"
79 #import "WebNSDataExtrasPrivate.h"
80 #import "WebNSDictionaryExtras.h"
81 #import "WebNSEventExtras.h"
82 #import "WebNSObjectExtras.h"
83 #import "WebNSPasteboardExtras.h"
84 #import "WebNSPrintOperationExtras.h"
85 #import "WebNSURLExtras.h"
86 #import "WebNSURLRequestExtras.h"
87 #import "WebNSUserDefaultsExtras.h"
88 #import "WebNSViewExtras.h"
89 #import "WebNodeHighlight.h"
90 #import "WebPDFView.h"
91 #import "WebPanelAuthenticationHandler.h"
92 #import "WebPasteboardHelper.h"
93 #import "WebPlatformStrategies.h"
94 #import "WebPluginDatabase.h"
95 #import "WebPluginHalterClient.h"
96 #import "WebPolicyDelegate.h"
97 #import "WebPreferenceKeysPrivate.h"
98 #import "WebPreferencesPrivate.h"
99 #import "WebScriptDebugDelegate.h"
100 #import "WebScriptWorldInternal.h"
101 #import "WebSystemInterface.h"
102 #import "WebTextCompletionController.h"
103 #import "WebTextIterator.h"
104 #import "WebUIDelegate.h"
105 #import "WebUIDelegatePrivate.h"
106 #import "WebVideoFullscreenController.h"
107 #import <CoreFoundation/CFSet.h>
108 #import <Foundation/NSURLConnection.h>
109 #import <JavaScriptCore/APICast.h>
110 #import <JavaScriptCore/JSValueRef.h>
111 #import <WebCore/AbstractDatabase.h>
112 #import <WebCore/ApplicationCacheStorage.h>
113 #import <WebCore/BackForwardList.h>
114 #import <WebCore/Cache.h>
115 #import <WebCore/ColorMac.h>
116 #import <WebCore/CSSComputedStyleDeclaration.h>
117 #import <WebCore/Cursor.h>
118 #import <WebCore/Document.h>
119 #import <WebCore/DocumentLoader.h>
120 #import <WebCore/DragController.h>
121 #import <WebCore/DragData.h>
122 #import <WebCore/Editor.h>
123 #import <WebCore/EventHandler.h>
124 #import <WebCore/ExceptionHandlers.h>
125 #import <WebCore/FocusController.h>
126 #import <WebCore/Frame.h>
127 #import <WebCore/FrameLoader.h>
128 #import <WebCore/FrameTree.h>
129 #import <WebCore/FrameView.h>
130 #import <WebCore/GCController.h>
131 #import <WebCore/HTMLMediaElement.h>
132 #import <WebCore/HTMLNames.h>
133 #import <WebCore/HistoryItem.h>
134 #import <WebCore/IconDatabase.h>
135 #import <WebCore/JSCSSStyleDeclaration.h>
136 #import <WebCore/JSElement.h>
137 #import <WebCore/Logging.h>
138 #import <WebCore/MIMETypeRegistry.h>
139 #import <WebCore/Page.h>
140 #import <WebCore/PageCache.h>
141 #import <WebCore/PageGroup.h>
142 #import <WebCore/PlatformMouseEvent.h>
143 #import <WebCore/ProgressTracker.h>
144 #import <WebCore/RenderWidget.h>
145 #import <WebCore/ResourceHandle.h>
146 #import <WebCore/RuntimeApplicationChecks.h>
147 #import <WebCore/SchemeRegistry.h>
148 #import <WebCore/ScriptController.h>
149 #import <WebCore/ScriptValue.h>
150 #import <WebCore/SecurityOrigin.h>
151 #import <WebCore/SelectionController.h>
152 #import <WebCore/Settings.h>
153 #import <WebCore/TextResourceDecoder.h>
154 #import <WebCore/ThreadCheck.h>
155 #import <WebCore/WebCoreObjCExtras.h>
156 #import <WebCore/WebCoreView.h>
157 #import <WebCore/Widget.h>
158 #import <WebKit/DOM.h>
159 #import <WebKit/DOMExtensions.h>
160 #import <WebKit/DOMPrivate.h>
161 #import <WebKitSystemInterface.h>
162 #import <mach-o/dyld.h>
163 #import <objc/objc-auto.h>
164 #import <objc/objc-runtime.h>
165 #import <runtime/ArrayPrototype.h>
166 #import <runtime/DateInstance.h>
167 #import <runtime/InitializeThreading.h>
168 #import <runtime/JSLock.h>
169 #import <runtime/JSValue.h>
170 #import <wtf/Assertions.h>
171 #import <wtf/HashTraits.h>
172 #import <wtf/RefCountedLeakCounter.h>
173 #import <wtf/RefPtr.h>
174 #import <wtf/StdLibExtras.h>
175 #import <wtf/Threading.h>
177 #if ENABLE(DASHBOARD_SUPPORT)
178 #import <WebKit/WebDashboardRegion.h>
181 #if ENABLE(CLIENT_BASED_GEOLOCATION)
182 #import <WebCore/GeolocationController.h>
183 #import <WebCore/GeolocationError.h>
186 #if ENABLE(VIDEO) && USE(GSTREAMER)
190 @interface NSSpellChecker (WebNSSpellCheckerDetails)
191 - (void)_preflightChosenSpellServer;
194 @interface NSView (WebNSViewDetails)
195 - (NSView *)_hitTest:(NSPoint *)aPoint dragTypes:(NSSet *)types;
196 - (void)_autoscrollForDraggingInfo:(id)dragInfo timeDelta:(NSTimeInterval)repeatDelta;
197 - (BOOL)_shouldAutoscrollForDraggingInfo:(id)dragInfo;
200 @interface NSWindow (WebNSWindowDetails)
201 - (id)_oldFirstResponderBeforeBecoming;
202 - (void)_enableScreenUpdatesIfNeeded;
203 - (BOOL)_wrapsCarbonWindow;
206 using namespace WebCore;
209 #if defined(__ppc__) || defined(__ppc64__)
210 #define PROCESSOR "PPC"
211 #elif defined(__i386__) || defined(__x86_64__)
212 #define PROCESSOR "Intel"
214 #error Unknown architecture
217 #define FOR_EACH_RESPONDER_SELECTOR(macro) \
219 macro(alignJustified) \
222 macro(capitalizeWord) \
223 macro(centerSelectionInVisibleArea) \
224 macro(changeAttributes) \
225 macro(changeBaseWritingDirection) \
226 macro(changeBaseWritingDirectionToLTR) \
227 macro(changeBaseWritingDirectionToRTL) \
229 macro(changeDocumentBackgroundColor) \
231 macro(changeSpelling) \
232 macro(checkSpelling) \
238 macro(deleteBackward) \
239 macro(deleteBackwardByDecomposingPreviousCharacter) \
240 macro(deleteForward) \
241 macro(deleteToBeginningOfLine) \
242 macro(deleteToBeginningOfParagraph) \
243 macro(deleteToEndOfLine) \
244 macro(deleteToEndOfParagraph) \
245 macro(deleteToMark) \
246 macro(deleteWordBackward) \
247 macro(deleteWordForward) \
248 macro(ignoreSpelling) \
250 macro(insertBacktab) \
251 macro(insertLineBreak) \
252 macro(insertNewline) \
253 macro(insertNewlineIgnoringFieldEditor) \
254 macro(insertParagraphSeparator) \
256 macro(insertTabIgnoringFieldEditor) \
257 macro(lowercaseWord) \
258 macro(makeBaseWritingDirectionLeftToRight) \
259 macro(makeBaseWritingDirectionRightToLeft) \
260 macro(makeTextWritingDirectionLeftToRight) \
261 macro(makeTextWritingDirectionNatural) \
262 macro(makeTextWritingDirectionRightToLeft) \
263 macro(moveBackward) \
264 macro(moveBackwardAndModifySelection) \
266 macro(moveDownAndModifySelection) \
268 macro(moveForwardAndModifySelection) \
270 macro(moveLeftAndModifySelection) \
271 macro(moveParagraphBackwardAndModifySelection) \
272 macro(moveParagraphForwardAndModifySelection) \
274 macro(moveRightAndModifySelection) \
275 macro(moveToBeginningOfDocument) \
276 macro(moveToBeginningOfDocumentAndModifySelection) \
277 macro(moveToBeginningOfLine) \
278 macro(moveToBeginningOfLineAndModifySelection) \
279 macro(moveToBeginningOfParagraph) \
280 macro(moveToBeginningOfParagraphAndModifySelection) \
281 macro(moveToBeginningOfSentence) \
282 macro(moveToBeginningOfSentenceAndModifySelection) \
283 macro(moveToEndOfDocument) \
284 macro(moveToEndOfDocumentAndModifySelection) \
285 macro(moveToEndOfLine) \
286 macro(moveToEndOfLineAndModifySelection) \
287 macro(moveToEndOfParagraph) \
288 macro(moveToEndOfParagraphAndModifySelection) \
289 macro(moveToEndOfSentence) \
290 macro(moveToEndOfSentenceAndModifySelection) \
291 macro(moveToLeftEndOfLine) \
292 macro(moveToLeftEndOfLineAndModifySelection) \
293 macro(moveToRightEndOfLine) \
294 macro(moveToRightEndOfLineAndModifySelection) \
296 macro(moveUpAndModifySelection) \
297 macro(moveWordBackward) \
298 macro(moveWordBackwardAndModifySelection) \
299 macro(moveWordForward) \
300 macro(moveWordForwardAndModifySelection) \
301 macro(moveWordLeft) \
302 macro(moveWordLeftAndModifySelection) \
303 macro(moveWordRight) \
304 macro(moveWordRightAndModifySelection) \
306 macro(orderFrontSubstitutionsPanel) \
308 macro(pageDownAndModifySelection) \
310 macro(pageUpAndModifySelection) \
312 macro(pasteAsPlainText) \
313 macro(pasteAsRichText) \
315 macro(performFindPanelAction) \
316 macro(scrollLineDown) \
317 macro(scrollLineUp) \
318 macro(scrollPageDown) \
319 macro(scrollPageUp) \
320 macro(scrollToBeginningOfDocument) \
321 macro(scrollToEndOfDocument) \
324 macro(selectParagraph) \
325 macro(selectSentence) \
326 macro(selectToMark) \
329 macro(showGuessPanel) \
330 macro(startSpeaking) \
331 macro(stopSpeaking) \
334 macro(swapWithMark) \
335 macro(takeFindStringFromSelection) \
336 macro(toggleBaseWritingDirection) \
340 macro(uppercaseWord) \
342 macro(yankAndSelect) \
344 #define WebKitOriginalTopPrintingMarginKey @"WebKitOriginalTopMargin"
345 #define WebKitOriginalBottomPrintingMarginKey @"WebKitOriginalBottomMargin"
347 #define KeyboardUIModeDidChangeNotification @"com.apple.KeyboardUIModeDidChange"
348 #define AppleKeyboardUIMode CFSTR("AppleKeyboardUIMode")
349 #define UniversalAccessDomain CFSTR("com.apple.universalaccess")
351 static BOOL s_didSetCacheModel;
352 static WebCacheModel s_cacheModel = WebCacheModelDocumentViewer;
355 static const char webViewIsOpen[] = "At least one WebView is still open.";
358 @interface NSObject (WebValidateWithoutDelegate)
359 - (BOOL)validateUserInterfaceItemWithoutDelegate:(id <NSValidatedUserInterfaceItem>)item;
362 @interface _WebSafeForwarder : NSObject
364 id target; // Non-retained. Don't retain delegates.
366 BOOL catchExceptions;
368 - (id)initWithTarget:(id)target defaultTarget:(id)defaultTarget catchExceptions:(BOOL)catchExceptions;
371 @interface WebView (WebFileInternal)
373 - (WebFrameView *)_frameViewAtWindowPoint:(NSPoint)point;
374 - (WebFrame *)_focusedFrame;
375 + (void)_preflightSpellChecker;
376 - (BOOL)_continuousCheckingAllowed;
377 - (NSResponder *)_responderForResponderOperations;
378 #if USE(ACCELERATED_COMPOSITING)
379 - (void)_clearLayerSyncLoopObserver;
381 #if ENABLE(VIDEO) && USE(GSTREAMER)
382 - (void)_clearGlibLoopObserver;
386 static void patchMailRemoveAttributesMethod();
388 NSString *WebElementDOMNodeKey = @"WebElementDOMNode";
389 NSString *WebElementFrameKey = @"WebElementFrame";
390 NSString *WebElementImageKey = @"WebElementImage";
391 NSString *WebElementImageAltStringKey = @"WebElementImageAltString";
392 NSString *WebElementImageRectKey = @"WebElementImageRect";
393 NSString *WebElementImageURLKey = @"WebElementImageURL";
394 NSString *WebElementIsSelectedKey = @"WebElementIsSelected";
395 NSString *WebElementLinkLabelKey = @"WebElementLinkLabel";
396 NSString *WebElementLinkTargetFrameKey = @"WebElementTargetFrame";
397 NSString *WebElementLinkTitleKey = @"WebElementLinkTitle";
398 NSString *WebElementLinkURLKey = @"WebElementLinkURL";
399 NSString *WebElementSpellingToolTipKey = @"WebElementSpellingToolTip";
400 NSString *WebElementTitleKey = @"WebElementTitle";
401 NSString *WebElementLinkIsLiveKey = @"WebElementLinkIsLive";
402 NSString *WebElementIsInScrollBarKey = @"WebElementIsInScrollBar";
403 NSString *WebElementIsContentEditableKey = @"WebElementIsContentEditableKey";
405 NSString *WebViewProgressStartedNotification = @"WebProgressStartedNotification";
406 NSString *WebViewProgressEstimateChangedNotification = @"WebProgressEstimateChangedNotification";
407 NSString *WebViewProgressFinishedNotification = @"WebProgressFinishedNotification";
409 NSString * const WebViewDidBeginEditingNotification = @"WebViewDidBeginEditingNotification";
410 NSString * const WebViewDidChangeNotification = @"WebViewDidChangeNotification";
411 NSString * const WebViewDidEndEditingNotification = @"WebViewDidEndEditingNotification";
412 NSString * const WebViewDidChangeTypingStyleNotification = @"WebViewDidChangeTypingStyleNotification";
413 NSString * const WebViewDidChangeSelectionNotification = @"WebViewDidChangeSelectionNotification";
415 enum { WebViewVersion = 4 };
417 #define timedLayoutSize 4096
419 static NSMutableSet *schemesWithRepresentationsSet;
421 NSString *_WebCanGoBackKey = @"canGoBack";
422 NSString *_WebCanGoForwardKey = @"canGoForward";
423 NSString *_WebEstimatedProgressKey = @"estimatedProgress";
424 NSString *_WebIsLoadingKey = @"isLoading";
425 NSString *_WebMainFrameIconKey = @"mainFrameIcon";
426 NSString *_WebMainFrameTitleKey = @"mainFrameTitle";
427 NSString *_WebMainFrameURLKey = @"mainFrameURL";
428 NSString *_WebMainFrameDocumentKey = @"mainFrameDocument";
430 NSString *_WebViewDidStartAcceleratedCompositingNotification = @"_WebViewDidStartAcceleratedCompositing";
432 @interface WebProgressItem : NSObject
435 long long bytesReceived;
436 long long estimatedLength;
440 @implementation WebProgressItem
443 static BOOL continuousSpellCheckingEnabled;
444 #ifndef BUILDING_ON_TIGER
445 static BOOL grammarCheckingEnabled;
447 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
448 static BOOL automaticQuoteSubstitutionEnabled;
449 static BOOL automaticLinkDetectionEnabled;
450 static BOOL automaticDashSubstitutionEnabled;
451 static BOOL automaticTextReplacementEnabled;
452 static BOOL automaticSpellingCorrectionEnabled;
455 @implementation WebView (AllWebViews)
457 static CFSetCallBacks NonRetainingSetCallbacks = {
466 static CFMutableSetRef allWebViewsSet;
468 + (void)_makeAllWebViewsPerformSelector:(SEL)selector
473 [(NSMutableSet *)allWebViewsSet makeObjectsPerformSelector:selector];
476 - (void)_removeFromAllWebViewsSet
479 CFSetRemoveValue(allWebViewsSet, self);
482 - (void)_addToAllWebViewsSet
485 allWebViewsSet = CFSetCreateMutable(NULL, 0, &NonRetainingSetCallbacks);
487 CFSetSetValue(allWebViewsSet, self);
492 @implementation WebView (WebPrivate)
494 static inline int callGestalt(OSType selector)
497 Gestalt(selector, &value);
501 // Uses underscores instead of dots because if "4." ever appears in a user agent string, old DHTML libraries treat it as Netscape 4.
502 static NSString *createMacOSXVersionString()
504 // Can't use -[NSProcessInfo operatingSystemVersionString] because it has too much stuff we don't want.
505 int major = callGestalt(gestaltSystemVersionMajor);
508 int minor = callGestalt(gestaltSystemVersionMinor);
509 int bugFix = callGestalt(gestaltSystemVersionBugFix);
511 return [[NSString alloc] initWithFormat:@"%d_%d_%d", major, minor, bugFix];
513 return [[NSString alloc] initWithFormat:@"%d_%d", major, minor];
514 return [[NSString alloc] initWithFormat:@"%d", major];
517 static NSString *createUserVisibleWebKitVersionString()
519 // If the version is 4 digits long or longer, then the first digit represents
520 // the version of the OS. Our user agent string should not include this first digit,
521 // so strip it off and report the rest as the version. <rdar://problem/4997547>
522 NSString *fullVersion = [[NSBundle bundleForClass:[WebView class]] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey];
523 NSRange nonDigitRange = [fullVersion rangeOfCharacterFromSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]];
524 if (nonDigitRange.location == NSNotFound && [fullVersion length] >= 4)
525 return [[fullVersion substringFromIndex:1] copy];
526 if (nonDigitRange.location != NSNotFound && nonDigitRange.location >= 4)
527 return [[fullVersion substringFromIndex:1] copy];
528 return [fullVersion copy];
531 + (NSString *)_standardUserAgentWithApplicationName:(NSString *)applicationName
533 // Note: Do *not* move the initialization of osVersion nor webKitVersion into the declaration.
534 // Garbage collection won't correctly mark the global variable in that case <rdar://problem/5733674>.
535 static NSString *osVersion;
536 static NSString *webKitVersion;
538 osVersion = createMacOSXVersionString();
540 webKitVersion = createUserVisibleWebKitVersionString();
541 NSString *language = [NSUserDefaults _webkit_preferredLanguageCode];
542 if ([applicationName length])
543 return [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; U; " PROCESSOR " Mac OS X %@; %@) AppleWebKit/%@ (KHTML, like Gecko) %@", osVersion, language, webKitVersion, applicationName];
544 return [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; U; " PROCESSOR " Mac OS X %@; %@) AppleWebKit/%@ (KHTML, like Gecko)", osVersion, language, webKitVersion];
547 + (void)_reportException:(JSValueRef)exception inContext:(JSContextRef)context
549 if (!exception || !context)
552 JSLock lock(SilenceAssertionsOnly);
553 JSC::ExecState* execState = toJS(context);
555 // Make sure the context has a DOMWindow global object, otherwise this context didn't originate from a WebView.
556 if (!toJSDOMWindow(execState->lexicalGlobalObject()))
559 reportException(execState, toJS(execState, exception));
562 static void WebKitInitializeApplicationCachePathIfNecessary()
564 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
565 static BOOL initialized = NO;
569 NSString *appName = [[NSBundle mainBundle] bundleIdentifier];
571 appName = [[NSProcessInfo processInfo] processName];
575 NSString* cacheDir = [NSString _webkit_localCacheDirectoryWithBundleIdentifier:appName];
577 cacheStorage().setCacheDirectory(cacheDir);
582 static bool runningLeopardMail()
584 #ifdef BUILDING_ON_LEOPARD
585 return applicationIsAppleMail();
590 static bool runningTigerMail()
592 #ifdef BUILDING_ON_TIGER
593 return applicationIsAppleMail();
598 static bool coreVideoHas7228836Fix()
600 #ifdef BUILDING_ON_LEOPARD
601 NSBundle* coreVideoFrameworkBundle = [NSBundle bundleWithPath:@"/System/Library/Frameworks/CoreVideo.framework"];
602 double version = [[coreVideoFrameworkBundle objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey] doubleValue];
603 return (version >= 48);
608 static bool shouldEnableLoadDeferring()
610 return !applicationIsAdobeInstaller();
613 - (void)_dispatchPendingLoadRequests
615 cache()->loader()->servePendingRequests();
618 - (void)_registerDraggedTypes
620 NSArray *editableTypes = [WebHTMLView _insertablePasteboardTypes];
621 NSArray *URLTypes = [NSPasteboard _web_dragTypesForURL];
622 NSMutableSet *types = [[NSMutableSet alloc] initWithArray:editableTypes];
623 [types addObjectsFromArray:URLTypes];
624 [self registerForDraggedTypes:[types allObjects]];
628 - (BOOL)_usesDocumentViews
630 return _private->usesDocumentViews;
633 - (void)_commonInitializationWithFrameName:(NSString *)frameName groupName:(NSString *)groupName usesDocumentViews:(BOOL)usesDocumentViews
635 WebCoreThreadViolationCheckRoundTwo();
638 WTF::RefCountedLeakCounter::suppressMessages(webViewIsOpen);
641 WebPreferences *standardPreferences = [WebPreferences standardPreferences];
642 [standardPreferences willAddToWebView];
644 _private->preferences = [standardPreferences retain];
645 _private->catchesDelegateExceptions = YES;
646 _private->mainFrameDocumentReady = NO;
647 _private->drawsBackground = YES;
648 _private->backgroundColor = [[NSColor colorWithDeviceWhite:1 alpha:1] retain];
649 _private->usesDocumentViews = usesDocumentViews;
650 _private->includesFlattenedCompositingLayersWhenDrawingToBitmap = YES;
652 WebFrameView *frameView = nil;
653 if (_private->usesDocumentViews) {
654 NSRect f = [self frame];
655 frameView = [[WebFrameView alloc] initWithFrame: NSMakeRect(0,0,f.size.width,f.size.height)];
656 [frameView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
657 [self addSubview:frameView];
661 static bool didOneTimeInitialization = false;
662 if (!didOneTimeInitialization) {
663 WebKitInitializeLoggingChannelsIfNecessary();
664 WebCore::InitializeLoggingChannelsIfNecessary();
665 [WebHistoryItem initWindowWatcherIfNecessary];
667 WebKitInitializeDatabasesIfNecessary();
669 WebKitInitializeApplicationCachePathIfNecessary();
670 patchMailRemoveAttributesMethod();
672 // Initialize our platform strategies.
673 WebPlatformStrategies::initialize();
675 didOneTimeInitialization = true;
678 Page::PageClients pageClients;
679 pageClients.chromeClient = new WebChromeClient(self);
680 pageClients.contextMenuClient = new WebContextMenuClient(self);
681 pageClients.editorClient = new WebEditorClient(self);
682 pageClients.dragClient = new WebDragClient(self);
683 pageClients.inspectorClient = new WebInspectorClient(self);
684 pageClients.pluginHalterClient = new WebPluginHalterClient(self);
685 #if ENABLE(CLIENT_BASED_GEOLOCATION)
686 pageClients.geolocationControllerClient = new WebGeolocationControllerClient(self);
688 #if ENABLE(DEVICE_ORIENTATION)
689 pageClients.deviceOrientationClient = new WebDeviceOrientationClient(self);
691 _private->page = new Page(pageClients);
693 _private->page->setCanStartMedia([self window]);
694 _private->page->settings()->setLocalStorageDatabasePath([[self preferences] _localStorageDatabasePath]);
696 [WebFrame _createMainFrameWithPage:_private->page frameName:frameName frameView:frameView];
698 #ifndef BUILDING_ON_TIGER
699 NSRunLoop *runLoop = [NSRunLoop mainRunLoop];
701 NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
704 if (WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_LOADING_DURING_COMMON_RUNLOOP_MODES))
705 [self scheduleInRunLoop:runLoop forMode:(NSString *)kCFRunLoopCommonModes];
707 [self scheduleInRunLoop:runLoop forMode:NSDefaultRunLoopMode];
709 [self _addToAllWebViewsSet];
710 [self setGroupName:groupName];
712 // If there's already a next key view (e.g., from a nib), wire it up to our
713 // contained frame view. In any case, wire our next key view up to the our
714 // contained frame view. This works together with our becomeFirstResponder
715 // and setNextKeyView overrides.
716 NSView *nextKeyView = [self nextKeyView];
717 if (nextKeyView && nextKeyView != frameView)
718 [frameView setNextKeyView:nextKeyView];
719 [super setNextKeyView:frameView];
721 if ([[self class] shouldIncludeInWebKitStatistics])
724 [self _registerDraggedTypes];
726 WebPreferences *prefs = [self preferences];
727 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:)
728 name:WebPreferencesChangedNotification object:prefs];
730 // Post a notification so the WebCore settings update.
731 [[self preferences] _postPreferencesChangesNotification];
733 if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_LOCAL_RESOURCE_SECURITY_RESTRICTION)) {
734 // Originally, we allowed all local loads.
735 SecurityOrigin::setLocalLoadPolicy(SecurityOrigin::AllowLocalLoadsForAll);
736 } else if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_MORE_STRICT_LOCAL_RESOURCE_SECURITY_RESTRICTION)) {
737 // Later, we allowed local loads for local URLs and documents loaded
738 // with substitute data.
739 SecurityOrigin::setLocalLoadPolicy(SecurityOrigin::AllowLocalLoadsForLocalAndSubstituteData);
742 if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_CONTENT_SNIFFING_FOR_FILE_URLS))
743 ResourceHandle::forceContentSniffing();
745 #if ENABLE(VIDEO) && USE(GSTREAMER)
746 [self _scheduleGlibContextIterations];
751 - (id)_initWithFrame:(NSRect)f frameName:(NSString *)frameName groupName:(NSString *)groupName usesDocumentViews:(BOOL)usesDocumentViews
753 self = [super initWithFrame:f];
757 #ifdef ENABLE_WEBKIT_UNSET_DYLD_FRAMEWORK_PATH
758 // DYLD_FRAMEWORK_PATH is used so Safari will load the development version of WebKit, which
759 // may not work with other WebKit applications. Unsetting DYLD_FRAMEWORK_PATH removes the
760 // need for Safari to unset it to prevent it from being passed to applications it launches.
761 // Unsetting it when a WebView is first created is as good a place as any.
762 // See <http://bugs.webkit.org/show_bug.cgi?id=4286> for more details.
763 if (getenv("WEBKIT_UNSET_DYLD_FRAMEWORK_PATH")) {
764 unsetenv("DYLD_FRAMEWORK_PATH");
765 unsetenv("WEBKIT_UNSET_DYLD_FRAMEWORK_PATH");
769 _private = [[WebViewPrivate alloc] init];
770 [self _commonInitializationWithFrameName:frameName groupName:groupName usesDocumentViews:usesDocumentViews];
771 [self setMaintainsBackForwardList: YES];
775 - (BOOL)_mustDrawUnionedRect:(NSRect)rect singleRects:(const NSRect *)rects count:(NSInteger)count
777 // If count == 0 here, use the rect passed in for drawing. This is a workaround for:
778 // <rdar://problem/3908282> REGRESSION (Mail): No drag image dragging selected text in Blot and Mail
779 // The reason for the workaround is that this method is called explicitly from the code
780 // to generate a drag image, and at that time, getRectsBeingDrawn:count: will return a zero count.
781 const int cRectThreshold = 10;
782 const float cWastedSpaceThreshold = 0.75f;
783 BOOL useUnionedRect = (count <= 1) || (count > cRectThreshold);
784 if (!useUnionedRect) {
785 // Attempt to guess whether or not we should use the unioned rect or the individual rects.
786 // We do this by computing the percentage of "wasted space" in the union. If that wasted space
787 // is too large, then we will do individual rect painting instead.
788 float unionPixels = (rect.size.width * rect.size.height);
789 float singlePixels = 0;
790 for (int i = 0; i < count; ++i)
791 singlePixels += rects[i].size.width * rects[i].size.height;
792 float wastedSpace = 1 - (singlePixels / unionPixels);
793 if (wastedSpace <= cWastedSpaceThreshold)
794 useUnionedRect = YES;
796 return useUnionedRect;
799 - (void)drawSingleRect:(NSRect)rect
801 ASSERT(!_private->usesDocumentViews);
803 [NSGraphicsContext saveGraphicsState];
807 [[self mainFrame] _drawRect:rect contentsOnly:NO];
809 [[self _UIDelegateForwarder] webView:self didDrawRect:rect];
811 if (WebNodeHighlight *currentHighlight = [self currentNodeHighlight])
812 [currentHighlight setNeedsUpdateInTargetViewRect:rect];
814 [NSGraphicsContext restoreGraphicsState];
815 } @catch (NSException *localException) {
816 [NSGraphicsContext restoreGraphicsState];
817 LOG_ERROR("Exception caught while drawing: %@", localException);
818 [localException raise];
824 return _private && !_private->usesDocumentViews;
827 - (void)setFrameSize:(NSSize)size
829 if (!_private->usesDocumentViews && !NSEqualSizes(_private->lastLayoutSize, size)) {
830 Frame* frame = [self _mainCoreFrame];
831 // FIXME: Viewless WebKit is broken with Safari banners (e.g., the Find banner). We'll have to figure out a way for
832 // Safari to communicate that this space is being consumed. For WebKit with document views, there's no
833 // need to do an explicit resize, since WebFrameViews have auto resizing turned on and will handle changing
834 // their bounds automatically. See <rdar://problem/6835573> for details.
835 frame->view()->resize(IntSize(size));
836 frame->view()->setNeedsLayout();
837 [self setNeedsDisplay:YES];
838 _private->lastLayoutSize = size;
841 [super setFrameSize:size];
844 #if USE(ACCELERATED_COMPOSITING) || !defined(BUILDING_ON_TIGER)
846 - (void)_viewWillDrawInternal
848 Frame* frame = [self _mainCoreFrame];
849 if (frame && frame->view())
850 frame->view()->updateLayoutAndStyleIfNeededRecursive();
855 #ifndef BUILDING_ON_TIGER
859 if (!_private->usesDocumentViews)
860 [self _viewWillDrawInternal];
861 [super viewWillDraw];
867 - (void)drawRect:(NSRect)rect
869 if (_private->usesDocumentViews)
870 return [super drawRect:rect];
872 ASSERT_MAIN_THREAD();
876 [self getRectsBeingDrawn:&rects count:&count];
879 if ([self _mustDrawUnionedRect:rect singleRects:rects count:count])
880 [self drawSingleRect:rect];
882 for (int i = 0; i < count; ++i)
883 [self drawSingleRect:rects[i]];
886 + (NSArray *)_supportedMIMETypes
888 // Load the plug-in DB allowing plug-ins to install types.
889 [WebPluginDatabase sharedDatabase];
890 return [[WebFrameView _viewTypesAllowImageTypeOmission:NO] allKeys];
893 + (NSArray *)_supportedFileExtensions
895 NSMutableSet *extensions = [[NSMutableSet alloc] init];
896 NSArray *MIMETypes = [self _supportedMIMETypes];
897 NSEnumerator *enumerator = [MIMETypes objectEnumerator];
899 while ((MIMEType = [enumerator nextObject]) != nil) {
900 NSArray *extensionsForType = WKGetExtensionsForMIMEType(MIMEType);
901 if (extensionsForType) {
902 [extensions addObjectsFromArray:extensionsForType];
905 NSArray *uniqueExtensions = [extensions allObjects];
906 [extensions release];
907 return uniqueExtensions;
910 static NSMutableSet *knownPluginMIMETypes()
912 static NSMutableSet *mimeTypes = [[NSMutableSet alloc] init];
917 + (void)_registerPluginMIMEType:(NSString *)MIMEType
919 [WebView registerViewClass:[WebHTMLView class] representationClass:[WebHTMLRepresentation class] forMIMEType:MIMEType];
920 [knownPluginMIMETypes() addObject:MIMEType];
923 + (void)_unregisterPluginMIMEType:(NSString *)MIMEType
925 [self _unregisterViewClassAndRepresentationClassForMIMEType:MIMEType];
926 [knownPluginMIMETypes() removeObject:MIMEType];
929 + (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType allowingPlugins:(BOOL)allowPlugins
931 MIMEType = [MIMEType lowercaseString];
932 Class viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:YES] _webkit_objectForMIMEType:MIMEType];
933 Class repClass = [[WebDataSource _repTypesAllowImageTypeOmission:YES] _webkit_objectForMIMEType:MIMEType];
935 if (!viewClass || !repClass || [[WebPDFView supportedMIMETypes] containsObject:MIMEType]) {
936 // Our optimization to avoid loading the plug-in DB and image types for the HTML case failed.
939 // Load the plug-in DB allowing plug-ins to install types.
940 [WebPluginDatabase sharedDatabase];
943 // Load the image types and get the view class and rep class. This should be the fullest picture of all handled types.
944 viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:NO] _webkit_objectForMIMEType:MIMEType];
945 repClass = [[WebDataSource _repTypesAllowImageTypeOmission:NO] _webkit_objectForMIMEType:MIMEType];
948 if (viewClass && repClass) {
949 if (viewClass == [WebHTMLView class] && repClass == [WebHTMLRepresentation class]) {
950 // Special-case WebHTMLView for text types that shouldn't be shown.
951 if ([[WebHTMLView unsupportedTextMIMETypes] containsObject:MIMEType])
954 // If the MIME type is a known plug-in we might not want to load it.
955 if (!allowPlugins && [knownPluginMIMETypes() containsObject:MIMEType]) {
956 BOOL isSupportedByWebKit = [[WebHTMLView supportedNonImageMIMETypes] containsObject:MIMEType] ||
957 [[WebHTMLView supportedMIMETypes] containsObject:MIMEType];
959 // If this is a known plug-in MIME type and WebKit can't show it natively, we don't want to show it.
960 if (!isSupportedByWebKit)
974 - (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType
976 if ([[self class] _viewClass:vClass andRepresentationClass:rClass forMIMEType:MIMEType allowingPlugins:[_private->preferences arePlugInsEnabled]])
979 if (_private->pluginDatabase) {
980 WebBasePluginPackage *pluginPackage = [_private->pluginDatabase pluginForMIMEType:MIMEType];
983 *vClass = [WebHTMLView class];
985 *rClass = [WebHTMLRepresentation class];
993 + (void)_setAlwaysUseATSU:(BOOL)f
995 [self _setAlwaysUsesComplexTextCodePath:f];
998 + (void)_setAlwaysUsesComplexTextCodePath:(BOOL)f
1000 Font::setCodePath(f ? Font::Complex : Font::Auto);
1003 + (BOOL)canCloseAllWebViews
1005 return DOMWindow::dispatchAllPendingBeforeUnloadEvents();
1008 + (void)closeAllWebViews
1010 DOMWindow::dispatchAllPendingUnloadEvents();
1012 // This will close the WebViews in a random order. Change this if close order is important.
1013 // Make a new set to avoid mutating the set we are enumerating.
1014 NSSet *webViewsToClose = [NSSet setWithSet:(NSSet *)allWebViewsSet];
1015 NSEnumerator *enumerator = [webViewsToClose objectEnumerator];
1016 while (WebView *webView = [enumerator nextObject])
1020 + (BOOL)canShowFile:(NSString *)path
1022 return [[self class] canShowMIMEType:[WebView _MIMETypeForFile:path]];
1025 + (NSString *)suggestedFileExtensionForMIMEType:(NSString *)type
1027 return WKGetPreferredExtensionForMIMEType(type);
1032 return !_private || _private->closed;
1035 - (void)_closePluginDatabases
1037 pluginDatabaseClientCount--;
1039 // Close both sets of plug-in databases because plug-ins need an opportunity to clean up files, etc.
1041 // Unload the WebView local plug-in database.
1042 if (_private->pluginDatabase) {
1043 [_private->pluginDatabase destroyAllPluginInstanceViews];
1044 [_private->pluginDatabase close];
1045 [_private->pluginDatabase release];
1046 _private->pluginDatabase = nil;
1049 // Keep the global plug-in database active until the app terminates to avoid having to reload plug-in bundles.
1050 if (!pluginDatabaseClientCount && applicationIsTerminating)
1051 [WebPluginDatabase closeSharedDatabase];
1054 - (void)_closeWithFastTeardown
1057 WTF::RefCountedLeakCounter::suppressMessages("At least one WebView was closed with fast teardown.");
1060 [[NSDistributedNotificationCenter defaultCenter] removeObserver:self];
1061 [[NSNotificationCenter defaultCenter] removeObserver:self];
1063 [self _closePluginDatabases];
1066 static bool fastDocumentTeardownEnabled()
1069 static bool enabled = ![[NSUserDefaults standardUserDefaults] boolForKey:WebKitEnableFullDocumentTeardownPreferenceKey];
1071 static bool initialized = false;
1072 static bool enabled = false;
1074 // This allows debug builds to default to not have fast teardown, so leak checking still works.
1075 // But still allow the WebKitEnableFullDocumentTeardown default to override it if present.
1076 NSNumber *setting = [[NSUserDefaults standardUserDefaults] objectForKey:WebKitEnableFullDocumentTeardownPreferenceKey];
1078 enabled = ![setting boolValue];
1085 // _close is here only for backward compatibility; clients and subclasses should use
1086 // public method -close instead.
1089 if (!_private || _private->closed)
1092 _private->closed = YES;
1093 [self _removeFromAllWebViewsSet];
1095 [self _closingEventHandling];
1098 WTF::RefCountedLeakCounter::cancelMessageSuppression(webViewIsOpen);
1101 // To quit the apps fast we skip document teardown, except plugins
1102 // need to be destroyed and unloaded.
1103 if (applicationIsTerminating && fastDocumentTeardownEnabled()) {
1104 [self _closeWithFastTeardown];
1109 [self _exitFullscreen];
1112 if (Frame* mainFrame = [self _mainCoreFrame])
1113 mainFrame->loader()->detachFromParent();
1115 [self setHostWindow:nil];
1117 [self setDownloadDelegate:nil];
1118 [self setEditingDelegate:nil];
1119 [self setFrameLoadDelegate:nil];
1120 [self setPolicyDelegate:nil];
1121 [self setResourceLoadDelegate:nil];
1122 [self setScriptDebugDelegate:nil];
1123 [self setUIDelegate:nil];
1125 [_private->inspector webViewClosed];
1127 // To avoid leaks, call removeDragCaret in case it wasn't called after moveDragCaretToPoint.
1128 [self removeDragCaret];
1130 // Deleteing the WebCore::Page will clear the page cache so we call destroy on
1131 // all the plug-ins in the page cache to break any retain cycles.
1132 // See comment in HistoryItem::releaseAllPendingPageCaches() for more information.
1133 Page* page = _private->page;
1137 if (_private->hasSpellCheckerDocumentTag) {
1138 [[NSSpellChecker sharedSpellChecker] closeSpellDocumentWithTag:_private->spellCheckerDocumentTag];
1139 _private->hasSpellCheckerDocumentTag = NO;
1142 #if USE(ACCELERATED_COMPOSITING)
1143 [self _clearLayerSyncLoopObserver];
1146 #if ENABLE(VIDEO) && USE(GSTREAMER)
1147 [self _clearGlibLoopObserver];
1150 [[NSDistributedNotificationCenter defaultCenter] removeObserver:self];
1151 [[NSNotificationCenter defaultCenter] removeObserver:self];
1153 [WebPreferences _removeReferenceForIdentifier:[self preferencesIdentifier]];
1155 WebPreferences *preferences = _private->preferences;
1156 _private->preferences = nil;
1157 [preferences didRemoveFromWebView];
1158 [preferences release];
1160 [self _closePluginDatabases];
1163 // Need this to make leak messages accurate.
1164 if (applicationIsTerminating) {
1165 gcController().garbageCollectNow();
1166 [WebCache setDisabled:YES];
1171 // Indicates if the WebView is in the midst of a user gesture.
1172 - (BOOL)_isProcessingUserGesture
1174 WebFrame *frame = [self mainFrame];
1175 return core(frame)->loader()->isProcessingUserGesture();
1178 + (NSString *)_MIMETypeForFile:(NSString *)path
1180 NSString *extension = [path pathExtension];
1181 NSString *MIMEType = nil;
1183 // Get the MIME type from the extension.
1184 if ([extension length] != 0) {
1185 MIMEType = WKGetMIMETypeForExtension(extension);
1188 // If we can't get a known MIME type from the extension, sniff.
1189 if ([MIMEType length] == 0 || [MIMEType isEqualToString:@"application/octet-stream"]) {
1190 NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:path];
1191 NSData *data = [handle readDataOfLength:WEB_GUESS_MIME_TYPE_PEEK_LENGTH];
1193 if ([data length] != 0) {
1194 MIMEType = [data _webkit_guessedMIMEType];
1196 if ([MIMEType length] == 0) {
1197 MIMEType = @"application/octet-stream";
1204 - (WebDownload *)_downloadURL:(NSURL *)URL
1208 NSURLRequest *request = [[NSURLRequest alloc] initWithURL:URL];
1209 WebDownload *download = [WebDownload _downloadWithRequest:request
1210 delegate:_private->downloadDelegate
1217 - (WebView *)_openNewWindowWithRequest:(NSURLRequest *)request
1219 NSDictionary *features = [[NSDictionary alloc] init];
1220 WebView *newWindowWebView = [[self _UIDelegateForwarder] webView:self
1221 createWebViewWithRequest:nil
1222 windowFeatures:features];
1224 if (!newWindowWebView)
1227 CallUIDelegate(newWindowWebView, @selector(webViewShow:));
1228 return newWindowWebView;
1231 - (WebInspector *)inspector
1233 if (!_private->inspector)
1234 _private->inspector = [[WebInspector alloc] initWithWebView:self];
1235 return _private->inspector;
1238 - (WebCore::Page*)page
1240 return _private->page;
1243 - (NSMenu *)_menuForElement:(NSDictionary *)element defaultItems:(NSArray *)items
1245 NSArray *defaultMenuItems = [[WebDefaultUIDelegate sharedUIDelegate] webView:self contextMenuItemsForElement:element defaultMenuItems:items];
1247 NSArray *menuItems = CallUIDelegate(self, @selector(webView:contextMenuItemsForElement:defaultMenuItems:), element, defaultMenuItems);
1251 unsigned count = [menuItems count];
1255 NSMenu *menu = [[NSMenu alloc] init];
1256 for (unsigned i = 0; i < count; i++)
1257 [menu addItem:[menuItems objectAtIndex:i]];
1259 return [menu autorelease];
1262 - (void)_mouseDidMoveOverElement:(NSDictionary *)dictionary modifierFlags:(NSUInteger)modifierFlags
1264 // We originally intended to call this delegate method sometimes with a nil dictionary, but due to
1265 // a bug dating back to WebKit 1.0 this delegate was never called with nil! Unfortunately we can't
1266 // start calling this with nil since it will break Adobe Help Viewer, and possibly other clients.
1269 CallUIDelegate(self, @selector(webView:mouseDidMoveOverElement:modifierFlags:), dictionary, modifierFlags);
1272 - (void)_loadBackForwardListFromOtherView:(WebView *)otherView
1274 if (!_private->page)
1277 if (!otherView->_private->page)
1280 // It turns out the right combination of behavior is done with the back/forward load
1281 // type. (See behavior matrix at the top of WebFramePrivate.) So we copy all the items
1282 // in the back forward list, and go to the current one.
1284 BackForwardList* backForwardList = _private->page->backForwardList();
1285 ASSERT(!backForwardList->currentItem()); // destination list should be empty
1287 BackForwardList* otherBackForwardList = otherView->_private->page->backForwardList();
1288 if (!otherBackForwardList->currentItem())
1289 return; // empty back forward list, bail
1291 HistoryItem* newItemToGoTo = 0;
1293 int lastItemIndex = otherBackForwardList->forwardListCount();
1294 for (int i = -otherBackForwardList->backListCount(); i <= lastItemIndex; ++i) {
1296 // If this item is showing , save away its current scroll and form state,
1297 // since that might have changed since loading and it is normally not saved
1298 // until we leave that page.
1299 otherView->_private->page->mainFrame()->loader()->history()->saveDocumentAndScrollState();
1301 RefPtr<HistoryItem> newItem = otherBackForwardList->itemAtIndex(i)->copy();
1303 newItemToGoTo = newItem.get();
1304 backForwardList->addItem(newItem.release());
1307 ASSERT(newItemToGoTo);
1308 _private->page->goToItem(newItemToGoTo, FrameLoadTypeIndexedBackForward);
1311 - (void)_setFormDelegate: (id<WebFormDelegate>)delegate
1313 _private->formDelegate = delegate;
1316 - (id<WebFormDelegate>)_formDelegate
1318 return _private->formDelegate;
1321 - (BOOL)_needsAdobeFrameReloadingQuirk
1323 static BOOL needsQuirk = WKAppVersionCheckLessThan(@"com.adobe.Acrobat", -1, 9.0)
1324 || WKAppVersionCheckLessThan(@"com.adobe.Acrobat.Pro", -1, 9.0)
1325 || WKAppVersionCheckLessThan(@"com.adobe.Reader", -1, 9.0)
1326 || WKAppVersionCheckLessThan(@"com.adobe.distiller", -1, 9.0)
1327 || WKAppVersionCheckLessThan(@"com.adobe.Contribute", -1, 4.2)
1328 || WKAppVersionCheckLessThan(@"com.adobe.dreamweaver-9.0", -1, 9.1)
1329 || WKAppVersionCheckLessThan(@"com.macromedia.fireworks", -1, 9.1)
1330 || WKAppVersionCheckLessThan(@"com.adobe.InCopy", -1, 5.1)
1331 || WKAppVersionCheckLessThan(@"com.adobe.InDesign", -1, 5.1)
1332 || WKAppVersionCheckLessThan(@"com.adobe.Soundbooth", -1, 2);
1337 - (BOOL)_needsLinkElementTextCSSQuirk
1339 static BOOL needsQuirk = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_LINK_ELEMENT_TEXT_CSS_QUIRK)
1340 && WKAppVersionCheckLessThan(@"com.e-frontier.shade10", -1, 10.6);
1344 - (BOOL)_needsKeyboardEventDisambiguationQuirks
1346 static BOOL needsQuirks = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_IE_COMPATIBLE_KEYBOARD_EVENT_DISPATCH) && !applicationIsSafari();
1350 - (BOOL)_needsFrameLoadDelegateRetainQuirk
1352 static BOOL needsQuirk = WKAppVersionCheckLessThan(@"com.equinux.iSale5", -1, 5.6);
1356 - (void)_preferencesChangedNotification:(NSNotification *)notification
1358 WebPreferences *preferences = (WebPreferences *)[notification object];
1359 ASSERT(preferences == [self preferences]);
1361 if (!_private->userAgentOverridden)
1362 _private->userAgent = String();
1364 // Cache this value so we don't have to read NSUserDefaults on each page load
1365 _private->useSiteSpecificSpoofing = [preferences _useSiteSpecificSpoofing];
1367 // Update corresponding WebCore Settings object.
1368 if (!_private->page)
1371 Settings* settings = _private->page->settings();
1373 settings->setCursiveFontFamily([preferences cursiveFontFamily]);
1374 settings->setDefaultFixedFontSize([preferences defaultFixedFontSize]);
1375 settings->setDefaultFontSize([preferences defaultFontSize]);
1376 settings->setDefaultTextEncodingName([preferences defaultTextEncodingName]);
1377 settings->setUsesEncodingDetector([preferences usesEncodingDetector]);
1378 settings->setFantasyFontFamily([preferences fantasyFontFamily]);
1379 settings->setFixedFontFamily([preferences fixedFontFamily]);
1380 settings->setForceFTPDirectoryListings([preferences _forceFTPDirectoryListings]);
1381 settings->setFTPDirectoryTemplatePath([preferences _ftpDirectoryTemplatePath]);
1382 settings->setLocalStorageDatabasePath([preferences _localStorageDatabasePath]);
1383 settings->setJavaEnabled([preferences isJavaEnabled]);
1384 settings->setJavaScriptEnabled([preferences isJavaScriptEnabled]);
1385 settings->setWebSecurityEnabled([preferences isWebSecurityEnabled]);
1386 settings->setAllowUniversalAccessFromFileURLs([preferences allowUniversalAccessFromFileURLs]);
1387 settings->setAllowFileAccessFromFileURLs([preferences allowFileAccessFromFileURLs]);
1388 settings->setJavaScriptCanOpenWindowsAutomatically([preferences javaScriptCanOpenWindowsAutomatically]);
1389 settings->setMinimumFontSize([preferences minimumFontSize]);
1390 settings->setMinimumLogicalFontSize([preferences minimumLogicalFontSize]);
1391 settings->setPluginsEnabled([preferences arePlugInsEnabled]);
1392 #if ENABLE(DATABASE)
1393 AbstractDatabase::setIsAvailable([preferences databasesEnabled]);
1395 settings->setLocalStorageEnabled([preferences localStorageEnabled]);
1396 settings->setExperimentalNotificationsEnabled([preferences experimentalNotificationsEnabled]);
1397 settings->setPrivateBrowsingEnabled([preferences privateBrowsingEnabled]);
1398 settings->setSansSerifFontFamily([preferences sansSerifFontFamily]);
1399 settings->setSerifFontFamily([preferences serifFontFamily]);
1400 settings->setStandardFontFamily([preferences standardFontFamily]);
1401 settings->setLoadsImagesAutomatically([preferences loadsImagesAutomatically]);
1402 settings->setShouldPrintBackgrounds([preferences shouldPrintBackgrounds]);
1403 settings->setTextAreasAreResizable([preferences textAreasAreResizable]);
1404 settings->setShrinksStandaloneImagesToFit([preferences shrinksStandaloneImagesToFit]);
1405 settings->setEditableLinkBehavior(core([preferences editableLinkBehavior]));
1406 settings->setEditingBehaviorType(core([preferences editingBehavior]));
1407 settings->setTextDirectionSubmenuInclusionBehavior(core([preferences textDirectionSubmenuInclusionBehavior]));
1408 settings->setDOMPasteAllowed([preferences isDOMPasteAllowed]);
1409 settings->setUsesPageCache([self usesPageCache]);
1410 settings->setShowsURLsInToolTips([preferences showsURLsInToolTips]);
1411 settings->setDeveloperExtrasEnabled([preferences developerExtrasEnabled]);
1412 settings->setAuthorAndUserStylesEnabled([preferences authorAndUserStylesEnabled]);
1413 settings->setApplicationChromeMode([preferences applicationChromeModeEnabled]);
1414 if ([preferences userStyleSheetEnabled]) {
1415 NSString* location = [[preferences userStyleSheetLocation] _web_originalDataAsString];
1416 if ([location isEqualToString:@"apple-dashboard://stylesheet"])
1417 location = @"file:///System/Library/PrivateFrameworks/DashboardClient.framework/Resources/widget.css";
1418 settings->setUserStyleSheetLocation([NSURL URLWithString:(location ? location : @"")]);
1420 settings->setUserStyleSheetLocation([NSURL URLWithString:@""]);
1421 settings->setNeedsAdobeFrameReloadingQuirk([self _needsAdobeFrameReloadingQuirk]);
1422 settings->setTreatsAnyTextCSSLinkAsStylesheet([self _needsLinkElementTextCSSQuirk]);
1423 settings->setNeedsKeyboardEventDisambiguationQuirks([self _needsKeyboardEventDisambiguationQuirks]);
1424 settings->setNeedsLeopardMailQuirks(runningLeopardMail());
1425 settings->setNeedsTigerMailQuirks(runningTigerMail());
1426 settings->setNeedsSiteSpecificQuirks(_private->useSiteSpecificSpoofing);
1427 settings->setWebArchiveDebugModeEnabled([preferences webArchiveDebugModeEnabled]);
1428 settings->setLocalFileContentSniffingEnabled([preferences localFileContentSniffingEnabled]);
1429 settings->setOfflineWebApplicationCacheEnabled([preferences offlineWebApplicationCacheEnabled]);
1430 settings->setZoomMode([preferences zoomsTextOnly] ? ZoomTextOnly : ZoomPage);
1431 settings->setJavaScriptCanAccessClipboard([preferences javaScriptCanAccessClipboard]);
1432 settings->setXSSAuditorEnabled([preferences isXSSAuditorEnabled]);
1433 settings->setEnforceCSSMIMETypeInNoQuirksMode(!WKAppVersionCheckLessThan(@"com.apple.iWeb", -1, 2.1));
1434 settings->setDNSPrefetchingEnabled([preferences isDNSPrefetchingEnabled]);
1436 // FIXME: Enabling accelerated compositing when WebGL is enabled causes tests to fail on Leopard which expect HW compositing to be disabled.
1437 // Until we fix that, I will comment out the test (CFM)
1438 settings->setAcceleratedCompositingEnabled((coreVideoHas7228836Fix() || [preferences webGLEnabled]) && [preferences acceleratedCompositingEnabled]);
1439 settings->setShowDebugBorders([preferences showDebugBorders]);
1440 settings->setShowRepaintCounter([preferences showRepaintCounter]);
1441 settings->setPluginAllowedRunTime([preferences pluginAllowedRunTime]);
1442 settings->setWebGLEnabled([preferences webGLEnabled]);
1443 settings->setLoadDeferringEnabled(shouldEnableLoadDeferring());
1444 settings->setFrameFlatteningEnabled([preferences isFrameFlatteningEnabled]);
1445 settings->setPaginateDuringLayoutEnabled([preferences paginateDuringLayoutEnabled]);
1446 #if ENABLE(FULLSCREEN_API)
1447 settings->setFullScreenEnabled([preferences fullScreenEnabled]);
1449 settings->setMemoryInfoEnabled([preferences memoryInfoEnabled]);
1451 // Application Cache Preferences are stored on the global cache storage manager, not in Settings.
1452 [WebApplicationCache setDefaultOriginQuota:[preferences applicationCacheDefaultOriginQuota]];
1455 static inline IMP getMethod(id o, SEL s)
1457 return [o respondsToSelector:s] ? [o methodForSelector:s] : 0;
1460 - (void)_cacheResourceLoadDelegateImplementations
1462 WebResourceDelegateImplementationCache *cache = &_private->resourceLoadDelegateImplementations;
1463 id delegate = _private->resourceProgressDelegate;
1466 bzero(cache, sizeof(WebResourceDelegateImplementationCache));
1470 cache->didCancelAuthenticationChallengeFunc = getMethod(delegate, @selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:));
1471 cache->didFailLoadingWithErrorFromDataSourceFunc = getMethod(delegate, @selector(webView:resource:didFailLoadingWithError:fromDataSource:));
1472 cache->didFinishLoadingFromDataSourceFunc = getMethod(delegate, @selector(webView:resource:didFinishLoadingFromDataSource:));
1473 cache->didLoadResourceFromMemoryCacheFunc = getMethod(delegate, @selector(webView:didLoadResourceFromMemoryCache:response:length:fromDataSource:));
1474 cache->didReceiveAuthenticationChallengeFunc = getMethod(delegate, @selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:));
1475 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
1476 cache->canAuthenticateAgainstProtectionSpaceFunc = getMethod(delegate, @selector(webView:resource:canAuthenticateAgainstProtectionSpace:forDataSource:));
1478 cache->didReceiveContentLengthFunc = getMethod(delegate, @selector(webView:resource:didReceiveContentLength:fromDataSource:));
1479 cache->didReceiveResponseFunc = getMethod(delegate, @selector(webView:resource:didReceiveResponse:fromDataSource:));
1480 cache->identifierForRequestFunc = getMethod(delegate, @selector(webView:identifierForInitialRequest:fromDataSource:));
1481 cache->plugInFailedWithErrorFunc = getMethod(delegate, @selector(webView:plugInFailedWithError:dataSource:));
1482 cache->willCacheResponseFunc = getMethod(delegate, @selector(webView:resource:willCacheResponse:fromDataSource:));
1483 cache->willSendRequestFunc = getMethod(delegate, @selector(webView:resource:willSendRequest:redirectResponse:fromDataSource:));
1484 cache->shouldUseCredentialStorageFunc = getMethod(delegate, @selector(webView:resource:shouldUseCredentialStorageForDataSource:));
1487 - (void)_cacheFrameLoadDelegateImplementations
1489 WebFrameLoadDelegateImplementationCache *cache = &_private->frameLoadDelegateImplementations;
1490 id delegate = _private->frameLoadDelegate;
1493 bzero(cache, sizeof(WebFrameLoadDelegateImplementationCache));
1497 cache->didCancelClientRedirectForFrameFunc = getMethod(delegate, @selector(webView:didCancelClientRedirectForFrame:));
1498 cache->didChangeLocationWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didChangeLocationWithinPageForFrame:));
1499 cache->didPushStateWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didPushStateWithinPageForFrame:));
1500 cache->didReplaceStateWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didReplaceStateWithinPageForFrame:));
1501 cache->didPopStateWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didPopStateWithinPageForFrame:));
1502 cache->didClearWindowObjectForFrameFunc = getMethod(delegate, @selector(webView:didClearWindowObject:forFrame:));
1503 cache->didClearWindowObjectForFrameInScriptWorldFunc = getMethod(delegate, @selector(webView:didClearWindowObjectForFrame:inScriptWorld:));
1504 cache->didClearInspectorWindowObjectForFrameFunc = getMethod(delegate, @selector(webView:didClearInspectorWindowObject:forFrame:));
1505 cache->didCommitLoadForFrameFunc = getMethod(delegate, @selector(webView:didCommitLoadForFrame:));
1506 cache->didFailLoadWithErrorForFrameFunc = getMethod(delegate, @selector(webView:didFailLoadWithError:forFrame:));
1507 cache->didFailProvisionalLoadWithErrorForFrameFunc = getMethod(delegate, @selector(webView:didFailProvisionalLoadWithError:forFrame:));
1508 cache->didFinishDocumentLoadForFrameFunc = getMethod(delegate, @selector(webView:didFinishDocumentLoadForFrame:));
1509 cache->didFinishLoadForFrameFunc = getMethod(delegate, @selector(webView:didFinishLoadForFrame:));
1510 cache->didFirstLayoutInFrameFunc = getMethod(delegate, @selector(webView:didFirstLayoutInFrame:));
1511 cache->didFirstVisuallyNonEmptyLayoutInFrameFunc = getMethod(delegate, @selector(webView:didFirstVisuallyNonEmptyLayoutInFrame:));
1512 cache->didHandleOnloadEventsForFrameFunc = getMethod(delegate, @selector(webView:didHandleOnloadEventsForFrame:));
1513 cache->didReceiveIconForFrameFunc = getMethod(delegate, @selector(webView:didReceiveIcon:forFrame:));
1514 cache->didReceiveServerRedirectForProvisionalLoadForFrameFunc = getMethod(delegate, @selector(webView:didReceiveServerRedirectForProvisionalLoadForFrame:));
1515 cache->didReceiveTitleForFrameFunc = getMethod(delegate, @selector(webView:didReceiveTitle:forFrame:));
1516 cache->didStartProvisionalLoadForFrameFunc = getMethod(delegate, @selector(webView:didStartProvisionalLoadForFrame:));
1517 cache->willCloseFrameFunc = getMethod(delegate, @selector(webView:willCloseFrame:));
1518 cache->willPerformClientRedirectToURLDelayFireDateForFrameFunc = getMethod(delegate, @selector(webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:));
1519 cache->windowScriptObjectAvailableFunc = getMethod(delegate, @selector(webView:windowScriptObjectAvailable:));
1520 cache->didDisplayInsecureContentFunc = getMethod(delegate, @selector(webViewDidDisplayInsecureContent:));
1521 cache->didRunInsecureContentFunc = getMethod(delegate, @selector(webView:didRunInsecureContent:));
1524 - (void)_cacheScriptDebugDelegateImplementations
1526 WebScriptDebugDelegateImplementationCache *cache = &_private->scriptDebugDelegateImplementations;
1527 id delegate = _private->scriptDebugDelegate;
1530 bzero(cache, sizeof(WebScriptDebugDelegateImplementationCache));
1534 cache->didParseSourceFunc = getMethod(delegate, @selector(webView:didParseSource:baseLineNumber:fromURL:sourceId:forWebFrame:));
1535 if (cache->didParseSourceFunc)
1536 cache->didParseSourceExpectsBaseLineNumber = YES;
1538 cache->didParseSourceFunc = getMethod(delegate, @selector(webView:didParseSource:fromURL:sourceId:forWebFrame:));
1540 cache->failedToParseSourceFunc = getMethod(delegate, @selector(webView:failedToParseSource:baseLineNumber:fromURL:withError:forWebFrame:));
1541 cache->didEnterCallFrameFunc = getMethod(delegate, @selector(webView:didEnterCallFrame:sourceId:line:forWebFrame:));
1542 cache->willExecuteStatementFunc = getMethod(delegate, @selector(webView:willExecuteStatement:sourceId:line:forWebFrame:));
1543 cache->willLeaveCallFrameFunc = getMethod(delegate, @selector(webView:willLeaveCallFrame:sourceId:line:forWebFrame:));
1544 cache->exceptionWasRaisedFunc = getMethod(delegate, @selector(webView:exceptionWasRaised:sourceId:line:forWebFrame:));
1547 - (void)_cacheHistoryDelegateImplementations
1549 WebHistoryDelegateImplementationCache *cache = &_private->historyDelegateImplementations;
1550 id delegate = _private->historyDelegate;
1553 bzero(cache, sizeof(WebHistoryDelegateImplementationCache));
1557 cache->navigatedFunc = getMethod(delegate, @selector(webView:didNavigateWithNavigationData:inFrame:));
1558 cache->clientRedirectFunc = getMethod(delegate, @selector(webView:didPerformClientRedirectFromURL:toURL:inFrame:));
1559 cache->serverRedirectFunc = getMethod(delegate, @selector(webView:didPerformServerRedirectFromURL:toURL:inFrame:));
1560 cache->setTitleFunc = getMethod(delegate, @selector(webView:updateHistoryTitle:forURL:));
1561 cache->populateVisitedLinksFunc = getMethod(delegate, @selector(populateVisitedLinksForWebView:));
1564 - (id)_policyDelegateForwarder
1566 if (!_private->policyDelegateForwarder)
1567 _private->policyDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->policyDelegate defaultTarget:[WebDefaultPolicyDelegate sharedPolicyDelegate] catchExceptions:_private->catchesDelegateExceptions];
1568 return _private->policyDelegateForwarder;
1571 - (id)_UIDelegateForwarder
1573 if (!_private->UIDelegateForwarder)
1574 _private->UIDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->UIDelegate defaultTarget:[WebDefaultUIDelegate sharedUIDelegate] catchExceptions:_private->catchesDelegateExceptions];
1575 return _private->UIDelegateForwarder;
1578 - (id)_editingDelegateForwarder
1580 // This can be called during window deallocation by QTMovieView in the QuickTime Cocoa Plug-in.
1581 // Not sure if that is a bug or not.
1585 if (!_private->editingDelegateForwarder)
1586 _private->editingDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->editingDelegate defaultTarget:[WebDefaultEditingDelegate sharedEditingDelegate] catchExceptions:_private->catchesDelegateExceptions];
1587 return _private->editingDelegateForwarder;
1590 - (void)_closeWindow
1592 [[self _UIDelegateForwarder] webViewClose:self];
1595 + (void)_unregisterViewClassAndRepresentationClassForMIMEType:(NSString *)MIMEType
1597 [[WebFrameView _viewTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType];
1598 [[WebDataSource _repTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType];
1600 // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
1601 // in the WebCore MIMEType registry. For now we're doing this in a safe, limited manner
1602 // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
1603 MIMETypeRegistry::getSupportedNonImageMIMETypes().remove(MIMEType);
1606 + (void)_registerViewClass:(Class)viewClass representationClass:(Class)representationClass forURLScheme:(NSString *)URLScheme
1608 NSString *MIMEType = [self _generatedMIMETypeForURLScheme:URLScheme];
1609 [self registerViewClass:viewClass representationClass:representationClass forMIMEType:MIMEType];
1611 // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
1612 // in the WebCore MIMEType registry. For now we're doing this in a safe, limited manner
1613 // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
1614 if ([viewClass class] == [WebHTMLView class])
1615 MIMETypeRegistry::getSupportedNonImageMIMETypes().add(MIMEType);
1617 // This is used to make _representationExistsForURLScheme faster.
1618 // Without this set, we'd have to create the MIME type each time.
1619 if (schemesWithRepresentationsSet == nil) {
1620 schemesWithRepresentationsSet = [[NSMutableSet alloc] init];
1622 [schemesWithRepresentationsSet addObject:[[[URLScheme lowercaseString] copy] autorelease]];
1625 + (NSString *)_generatedMIMETypeForURLScheme:(NSString *)URLScheme
1627 return [@"x-apple-web-kit/" stringByAppendingString:[URLScheme lowercaseString]];
1630 + (BOOL)_representationExistsForURLScheme:(NSString *)URLScheme
1632 return [schemesWithRepresentationsSet containsObject:[URLScheme lowercaseString]];
1635 + (BOOL)_canHandleRequest:(NSURLRequest *)request forMainFrame:(BOOL)forMainFrame
1637 // FIXME: If <rdar://problem/5217309> gets fixed, this check can be removed.
1641 if ([NSURLConnection canHandleRequest:request])
1644 NSString *scheme = [[request URL] scheme];
1646 // Representations for URL schemes work at the top level.
1647 if (forMainFrame && [self _representationExistsForURLScheme:scheme])
1650 return [scheme _webkit_isCaseInsensitiveEqualToString:@"applewebdata"];
1653 + (BOOL)_canHandleRequest:(NSURLRequest *)request
1655 return [self _canHandleRequest:request forMainFrame:YES];
1658 + (NSString *)_decodeData:(NSData *)data
1660 HTMLNames::init(); // this method is used for importing bookmarks at startup, so HTMLNames are likely to be uninitialized yet
1661 RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("text/html"); // bookmark files are HTML
1662 String result = decoder->decode(static_cast<const char*>([data bytes]), [data length]);
1663 result += decoder->flush();
1667 - (void)_pushPerformingProgrammaticFocus
1669 _private->programmaticFocusCount++;
1672 - (void)_popPerformingProgrammaticFocus
1674 _private->programmaticFocusCount--;
1677 - (BOOL)_isPerformingProgrammaticFocus
1679 return _private->programmaticFocusCount != 0;
1682 - (void)_didChangeValueForKey: (NSString *)key
1684 LOG (Bindings, "calling didChangeValueForKey: %@", key);
1685 [self didChangeValueForKey: key];
1688 - (void)_willChangeValueForKey: (NSString *)key
1690 LOG (Bindings, "calling willChangeValueForKey: %@", key);
1691 [self willChangeValueForKey: key];
1694 + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key {
1695 static NSSet *manualNotifyKeys = nil;
1696 if (!manualNotifyKeys)
1697 manualNotifyKeys = [[NSSet alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey,
1698 _WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, _WebMainFrameDocumentKey,
1700 if ([manualNotifyKeys containsObject:key])
1705 - (NSArray *)_declaredKeys {
1706 static NSArray *declaredKeys = nil;
1708 declaredKeys = [[NSArray alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey,
1709 _WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, _WebMainFrameDocumentKey, nil];
1710 return declaredKeys;
1713 - (void)setObservationInfo:(void *)info
1715 _private->observationInfo = info;
1718 - (void *)observationInfo
1720 return _private->observationInfo;
1723 - (void)_willChangeBackForwardKeys
1725 [self _willChangeValueForKey: _WebCanGoBackKey];
1726 [self _willChangeValueForKey: _WebCanGoForwardKey];
1729 - (void)_didChangeBackForwardKeys
1731 [self _didChangeValueForKey: _WebCanGoBackKey];
1732 [self _didChangeValueForKey: _WebCanGoForwardKey];
1735 - (void)_didStartProvisionalLoadForFrame:(WebFrame *)frame
1737 [self _willChangeBackForwardKeys];
1738 if (frame == [self mainFrame]){
1739 // Force an observer update by sending a will/did.
1740 [self _willChangeValueForKey: _WebIsLoadingKey];
1741 [self _didChangeValueForKey: _WebIsLoadingKey];
1743 [self _willChangeValueForKey: _WebMainFrameURLKey];
1746 [NSApp setWindowsNeedUpdate:YES];
1749 - (void)_didCommitLoadForFrame:(WebFrame *)frame
1751 if (frame == [self mainFrame])
1752 [self _didChangeValueForKey: _WebMainFrameURLKey];
1753 [NSApp setWindowsNeedUpdate:YES];
1756 - (void)_didFinishLoadForFrame:(WebFrame *)frame
1758 [self _didChangeBackForwardKeys];
1759 if (frame == [self mainFrame]){
1760 // Force an observer update by sending a will/did.
1761 [self _willChangeValueForKey: _WebIsLoadingKey];
1762 [self _didChangeValueForKey: _WebIsLoadingKey];
1764 [NSApp setWindowsNeedUpdate:YES];
1767 - (void)_didFailLoadWithError:(NSError *)error forFrame:(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)_didFailProvisionalLoadWithError:(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 [self _didChangeValueForKey: _WebMainFrameURLKey];
1788 [NSApp setWindowsNeedUpdate:YES];
1791 - (NSCachedURLResponse *)_cachedResponseForURL:(NSURL *)URL
1793 NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:URL];
1794 [request _web_setHTTPUserAgent:[self userAgentForURL:URL]];
1795 NSCachedURLResponse *cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:request];
1797 return cachedResponse;
1800 - (void)_writeImageForElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
1802 NSURL *linkURL = [element objectForKey:WebElementLinkURLKey];
1803 DOMElement *domElement = [element objectForKey:WebElementDOMNodeKey];
1804 [pasteboard _web_writeImage:(NSImage *)(domElement ? nil : [element objectForKey:WebElementImageKey])
1806 URL:linkURL ? linkURL : (NSURL *)[element objectForKey:WebElementImageURLKey]
1807 title:[element objectForKey:WebElementImageAltStringKey]
1808 archive:[[element objectForKey:WebElementDOMNodeKey] webArchive]
1813 - (void)_writeLinkElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
1815 [pasteboard _web_writeURL:[element objectForKey:WebElementLinkURLKey]
1816 andTitle:[element objectForKey:WebElementLinkLabelKey]
1820 - (void)_setInitiatedDrag:(BOOL)initiatedDrag
1822 if (!_private->page)
1824 _private->page->dragController()->setDidInitiateDrag(initiatedDrag);
1827 #if ENABLE(DASHBOARD_SUPPORT)
1829 #define DASHBOARD_CONTROL_LABEL @"control"
1831 - (void)_addControlRect:(NSRect)bounds clip:(NSRect)clip fromView:(NSView *)view toDashboardRegions:(NSMutableDictionary *)regions
1833 NSRect adjustedBounds = bounds;
1834 adjustedBounds.origin = [self convertPoint:bounds.origin fromView:view];
1835 adjustedBounds.origin.y = [self bounds].size.height - adjustedBounds.origin.y;
1836 adjustedBounds.size = bounds.size;
1838 NSRect adjustedClip;
1839 adjustedClip.origin = [self convertPoint:clip.origin fromView:view];
1840 adjustedClip.origin.y = [self bounds].size.height - adjustedClip.origin.y;
1841 adjustedClip.size = clip.size;
1843 WebDashboardRegion *region = [[WebDashboardRegion alloc] initWithRect:adjustedBounds
1844 clip:adjustedClip type:WebDashboardRegionTypeScrollerRectangle];
1845 NSMutableArray *scrollerRegions = [regions objectForKey:DASHBOARD_CONTROL_LABEL];
1846 if (!scrollerRegions) {
1847 scrollerRegions = [[NSMutableArray alloc] init];
1848 [regions setObject:scrollerRegions forKey:DASHBOARD_CONTROL_LABEL];
1849 [scrollerRegions release];
1851 [scrollerRegions addObject:region];
1855 - (void)_addScrollerDashboardRegionsForFrameView:(FrameView*)frameView dashboardRegions:(NSMutableDictionary *)regions
1857 NSView *documentView = [[kit(frameView->frame()) frameView] documentView];
1859 const HashSet<RefPtr<Widget> >* children = frameView->children();
1860 HashSet<RefPtr<Widget> >::const_iterator end = children->end();
1861 for (HashSet<RefPtr<Widget> >::const_iterator it = children->begin(); it != end; ++it) {
1862 Widget* widget = (*it).get();
1863 if (widget->isFrameView()) {
1864 [self _addScrollerDashboardRegionsForFrameView:static_cast<FrameView*>(widget) dashboardRegions:regions];
1868 if (!widget->isScrollbar())
1871 // FIXME: This should really pass an appropriate clip, but our first try got it wrong, and
1872 // it's not common to need this to be correct in Dashboard widgets.
1873 NSRect bounds = widget->frameRect();
1874 [self _addControlRect:bounds clip:bounds fromView:documentView toDashboardRegions:regions];
1878 - (void)_addScrollerDashboardRegions:(NSMutableDictionary *)regions from:(NSArray *)views
1880 // Add scroller regions for NSScroller and WebCore scrollbars
1881 NSUInteger count = [views count];
1882 for (NSUInteger i = 0; i < count; i++) {
1883 NSView *view = [views objectAtIndex:i];
1885 if ([view isKindOfClass:[WebHTMLView class]]) {
1886 if (Frame* coreFrame = core([(WebHTMLView*)view _frame])) {
1887 if (FrameView* coreView = coreFrame->view())
1888 [self _addScrollerDashboardRegionsForFrameView:coreView dashboardRegions:regions];
1890 } else if ([view isKindOfClass:[NSScroller class]]) {
1891 // AppKit places absent scrollers at -100,-100
1892 if ([view frame].origin.y < 0)
1894 [self _addControlRect:[view bounds] clip:[view visibleRect] fromView:view toDashboardRegions:regions];
1896 [self _addScrollerDashboardRegions:regions from:[view subviews]];
1900 - (void)_addScrollerDashboardRegions:(NSMutableDictionary *)regions
1902 [self _addScrollerDashboardRegions:regions from:[self subviews]];
1905 - (NSDictionary *)_dashboardRegions
1907 // Only return regions from main frame.
1908 Frame* mainFrame = [self _mainCoreFrame];
1911 NSMutableDictionary *regions = mainFrame->dashboardRegionsDictionary();
1912 [self _addScrollerDashboardRegions:regions];
1916 - (void)_setDashboardBehavior:(WebDashboardBehavior)behavior to:(BOOL)flag
1918 // FIXME: Remove this blanket assignment once Dashboard and Dashcode implement
1919 // specific support for the backward compatibility mode flag.
1920 if (behavior == WebDashboardBehaviorAllowWheelScrolling && flag == NO && _private->page)
1921 _private->page->settings()->setUsesDashboardBackwardCompatibilityMode(true);
1924 case WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows: {
1925 _private->dashboardBehaviorAlwaysSendMouseEventsToAllWindows = flag;
1928 case WebDashboardBehaviorAlwaysSendActiveNullEventsToPlugIns: {
1929 _private->dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns = flag;
1932 case WebDashboardBehaviorAlwaysAcceptsFirstMouse: {
1933 _private->dashboardBehaviorAlwaysAcceptsFirstMouse = flag;
1936 case WebDashboardBehaviorAllowWheelScrolling: {
1937 _private->dashboardBehaviorAllowWheelScrolling = flag;
1940 case WebDashboardBehaviorUseBackwardCompatibilityMode: {
1942 _private->page->settings()->setUsesDashboardBackwardCompatibilityMode(flag);
1948 - (BOOL)_dashboardBehavior:(WebDashboardBehavior)behavior
1951 case WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows: {
1952 return _private->dashboardBehaviorAlwaysSendMouseEventsToAllWindows;
1954 case WebDashboardBehaviorAlwaysSendActiveNullEventsToPlugIns: {
1955 return _private->dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns;
1957 case WebDashboardBehaviorAlwaysAcceptsFirstMouse: {
1958 return _private->dashboardBehaviorAlwaysAcceptsFirstMouse;
1960 case WebDashboardBehaviorAllowWheelScrolling: {
1961 return _private->dashboardBehaviorAllowWheelScrolling;
1963 case WebDashboardBehaviorUseBackwardCompatibilityMode: {
1964 return _private->page && _private->page->settings()->usesDashboardBackwardCompatibilityMode();
1970 #endif /* ENABLE(DASHBOARD_SUPPORT) */
1972 + (void)_setShouldUseFontSmoothing:(BOOL)f
1974 Font::setShouldUseSmoothing(f);
1977 + (BOOL)_shouldUseFontSmoothing
1979 return Font::shouldUseSmoothing();
1982 + (void)_setUsesTestModeFocusRingColor:(BOOL)f
1984 setUsesTestModeFocusRingColor(f);
1987 + (BOOL)_usesTestModeFocusRingColor
1989 return usesTestModeFocusRingColor();
1992 - (void)setAlwaysShowVerticalScroller:(BOOL)flag
1994 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
1996 [scrollview setVerticalScrollingMode:ScrollbarAlwaysOn andLock:YES];
1998 [scrollview setVerticalScrollingModeLocked:NO];
1999 [scrollview setVerticalScrollingMode:ScrollbarAuto andLock:NO];
2003 - (BOOL)alwaysShowVerticalScroller
2005 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
2006 return [scrollview verticalScrollingModeLocked] && [scrollview verticalScrollingMode] == ScrollbarAlwaysOn;
2009 - (void)setAlwaysShowHorizontalScroller:(BOOL)flag
2011 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
2013 [scrollview setHorizontalScrollingMode:ScrollbarAlwaysOn andLock:YES];
2015 [scrollview setHorizontalScrollingModeLocked:NO];
2016 [scrollview setHorizontalScrollingMode:ScrollbarAuto andLock:NO];
2020 - (void)setProhibitsMainFrameScrolling:(BOOL)prohibits
2022 if (Frame* mainFrame = [self _mainCoreFrame])
2023 mainFrame->view()->setProhibitsScrolling(prohibits);
2026 - (BOOL)alwaysShowHorizontalScroller
2028 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
2029 return [scrollview horizontalScrollingModeLocked] && [scrollview horizontalScrollingMode] == ScrollbarAlwaysOn;
2032 - (void)_setInViewSourceMode:(BOOL)flag
2034 if (Frame* mainFrame = [self _mainCoreFrame])
2035 mainFrame->setInViewSourceMode(flag);
2038 - (BOOL)_inViewSourceMode
2040 Frame* mainFrame = [self _mainCoreFrame];
2041 return mainFrame && mainFrame->inViewSourceMode();
2044 - (void)_setUseFastImageScalingMode:(BOOL)flag
2046 if (_private->page && _private->page->inLowQualityImageInterpolationMode() != flag) {
2047 _private->page->setInLowQualityImageInterpolationMode(flag);
2048 [self setNeedsDisplay:YES];
2052 - (BOOL)_inFastImageScalingMode
2055 return _private->page->inLowQualityImageInterpolationMode();
2059 - (BOOL)_cookieEnabled
2062 return _private->page->cookieEnabled();
2066 - (void)_setCookieEnabled:(BOOL)enable
2069 _private->page->setCookieEnabled(enable);
2072 - (void)_setAdditionalWebPlugInPaths:(NSArray *)newPaths
2074 if (!_private->pluginDatabase)
2075 _private->pluginDatabase = [[WebPluginDatabase alloc] init];
2077 [_private->pluginDatabase setPlugInPaths:newPaths];
2078 [_private->pluginDatabase refresh];
2081 - (void)_attachScriptDebuggerToAllFrames
2083 for (Frame* frame = [self _mainCoreFrame]; frame; frame = frame->tree()->traverseNext())
2084 [kit(frame) _attachScriptDebugger];
2087 - (void)_detachScriptDebuggerFromAllFrames
2089 for (Frame* frame = [self _mainCoreFrame]; frame; frame = frame->tree()->traverseNext())
2090 [kit(frame) _detachScriptDebugger];
2093 - (void)setBackgroundColor:(NSColor *)backgroundColor
2095 if ([_private->backgroundColor isEqual:backgroundColor])
2098 id old = _private->backgroundColor;
2099 _private->backgroundColor = [backgroundColor retain];
2102 [[self mainFrame] _updateBackgroundAndUpdatesWhileOffscreen];
2105 - (NSColor *)backgroundColor
2107 return _private->backgroundColor;
2110 - (BOOL)defersCallbacks
2112 if (!_private->page)
2114 return _private->page->defersLoading();
2117 - (void)setDefersCallbacks:(BOOL)defer
2119 if (!_private->page)
2121 return _private->page->setDefersLoading(defer);
2124 // For backwards compatibility with the WebBackForwardList API, we honor both
2125 // a per-WebView and a per-preferences setting for whether to use the page cache.
2127 - (BOOL)usesPageCache
2129 return _private->usesPageCache && [[self preferences] usesPageCache];
2132 - (void)setUsesPageCache:(BOOL)usesPageCache
2134 _private->usesPageCache = usesPageCache;
2136 // Post a notification so the WebCore settings update.
2137 [[self preferences] _postPreferencesChangesNotification];
2140 - (WebHistoryItem *)_globalHistoryItem
2142 if (!_private->page)
2144 return kit(_private->page->globalHistoryItem());
2147 - (WebTextIterator *)textIteratorForRect:(NSRect)rect
2149 IntPoint rectStart(rect.origin.x, rect.origin.y);
2150 IntPoint rectEnd(rect.origin.x + rect.size.width, rect.origin.y + rect.size.height);
2152 Frame* coreFrame = [self _mainCoreFrame];
2156 VisibleSelection selectionInsideRect(coreFrame->visiblePositionForPoint(rectStart), coreFrame->visiblePositionForPoint(rectEnd));
2158 return [[[WebTextIterator alloc] initWithRange:kit(selectionInsideRect.toNormalizedRange().get())] autorelease];
2161 - (void)handleAuthenticationForResource:(id)identifier challenge:(NSURLAuthenticationChallenge *)challenge fromDataSource:(WebDataSource *)dataSource
2163 NSWindow *window = [self hostWindow] ? [self hostWindow] : [self window];
2164 [[WebPanelAuthenticationHandler sharedHandler] startAuthentication:challenge window:window];
2167 - (void)_clearUndoRedoOperations
2169 if (!_private->page)
2171 _private->page->clearUndoRedoOperations();
2174 - (void)_setCatchesDelegateExceptions:(BOOL)f
2176 _private->catchesDelegateExceptions = f;
2179 - (BOOL)_catchesDelegateExceptions
2181 return _private->catchesDelegateExceptions;
2184 - (void)_executeCoreCommandByName:(NSString *)name value:(NSString *)value
2186 Frame* coreFrame = [self _mainCoreFrame];
2189 coreFrame->editor()->command(name).execute(value);
2192 - (void)_setCustomHTMLTokenizerTimeDelay:(double)timeDelay
2194 if (!_private->page)
2196 return _private->page->setCustomHTMLTokenizerTimeDelay(timeDelay);
2199 - (void)_setCustomHTMLTokenizerChunkSize:(int)chunkSize
2201 if (!_private->page)
2203 return _private->page->setCustomHTMLTokenizerChunkSize(chunkSize);
2206 - (void)_clearMainFrameName
2208 _private->page->mainFrame()->tree()->clearName();
2211 - (void)setSelectTrailingWhitespaceEnabled:(BOOL)flag
2213 _private->selectTrailingWhitespaceEnabled = flag;
2215 [self setSmartInsertDeleteEnabled:false];
2218 - (BOOL)isSelectTrailingWhitespaceEnabled
2220 return _private->selectTrailingWhitespaceEnabled;
2223 - (void)setMemoryCacheDelegateCallsEnabled:(BOOL)enabled
2225 _private->page->setMemoryCacheClientCallsEnabled(enabled);
2228 - (BOOL)areMemoryCacheDelegateCallsEnabled
2230 return _private->page->areMemoryCacheClientCallsEnabled();
2233 - (void)_setJavaScriptURLsAreAllowed:(BOOL)areAllowed
2235 _private->page->setJavaScriptURLsAreAllowed(areAllowed);
2238 + (NSCursor *)_pointingHandCursor
2240 return handCursor().platformCursor();
2243 - (BOOL)_postsAcceleratedCompositingNotifications
2245 #if USE(ACCELERATED_COMPOSITING)
2246 return _private->postsAcceleratedCompositingNotifications;
2252 - (void)_setPostsAcceleratedCompositingNotifications:(BOOL)flag
2254 #if USE(ACCELERATED_COMPOSITING)
2255 _private->postsAcceleratedCompositingNotifications = flag;
2259 - (BOOL)_isUsingAcceleratedCompositing
2261 #if USE(ACCELERATED_COMPOSITING)
2262 if (_private->usesDocumentViews) {
2263 Frame* coreFrame = [self _mainCoreFrame];
2264 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
2265 NSView *documentView = [[kit(frame) frameView] documentView];
2266 if ([documentView isKindOfClass:[WebHTMLView class]] && [(WebHTMLView *)documentView _isUsingAcceleratedCompositing])
2274 - (BOOL)_isSoftwareRenderable
2276 #if USE(ACCELERATED_COMPOSITING)
2277 if (_private->usesDocumentViews) {
2278 Frame* coreFrame = [self _mainCoreFrame];
2279 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
2280 if (FrameView* view = frame->view()) {
2281 if (!view->isSoftwareRenderable())
2290 - (void)_setIncludesFlattenedCompositingLayersWhenDrawingToBitmap:(BOOL)flag
2292 _private->includesFlattenedCompositingLayersWhenDrawingToBitmap = flag;
2295 - (BOOL)_includesFlattenedCompositingLayersWhenDrawingToBitmap
2297 return _private->includesFlattenedCompositingLayersWhenDrawingToBitmap;
2300 #if ENABLE(NETSCAPE_PLUGIN_API)
2301 static WebBaseNetscapePluginView *_pluginViewForNode(DOMNode *node)
2306 Node* coreNode = core(node);
2310 RenderObject* renderer = coreNode->renderer();
2311 if (!renderer || !renderer->isWidget())
2314 Widget* widget = toRenderWidget(renderer)->widget();
2315 if (!widget || !widget->platformWidget())
2318 NSView *view = widget->platformWidget();
2319 if (![view isKindOfClass:[WebBaseNetscapePluginView class]])
2322 return (WebBaseNetscapePluginView *)view;
2324 #endif // ENABLE(NETSCAPE_PLUGIN_API)
2326 + (BOOL)_isNodeHaltedPlugin:(DOMNode *)node
2328 #if ENABLE(NETSCAPE_PLUGIN_API)
2329 return [_pluginViewForNode(node) isHalted];
2335 + (BOOL)_hasPluginForNodeBeenHalted:(DOMNode *)node
2337 #if ENABLE(NETSCAPE_PLUGIN_API)
2338 return [_pluginViewForNode(node) hasBeenHalted];
2343 + (void)_restartHaltedPluginForNode:(DOMNode *)node
2345 #if ENABLE(NETSCAPE_PLUGIN_API)
2349 [_pluginViewForNode(node) resumeFromHalt];
2353 - (NSPasteboard *)_insertionPasteboard
2355 return _private ? _private->insertionPasteboard : nil;
2358 + (void)_addOriginAccessWhitelistEntryWithSourceOrigin:(NSString *)sourceOrigin destinationProtocol:(NSString *)destinationProtocol destinationHost:(NSString *)destinationHost allowDestinationSubdomains:(BOOL)allowDestinationSubdomains
2360 SecurityOrigin::addOriginAccessWhitelistEntry(*SecurityOrigin::createFromString(sourceOrigin), destinationProtocol, destinationHost, allowDestinationSubdomains);
2363 + (void)_removeOriginAccessWhitelistEntryWithSourceOrigin:(NSString *)sourceOrigin destinationProtocol:(NSString *)destinationProtocol destinationHost:(NSString *)destinationHost allowDestinationSubdomains:(BOOL)allowDestinationSubdomains
2365 SecurityOrigin::removeOriginAccessWhitelistEntry(*SecurityOrigin::createFromString(sourceOrigin), destinationProtocol, destinationHost, allowDestinationSubdomains);
2368 +(void)_resetOriginAccessWhitelists
2370 SecurityOrigin::resetOriginAccessWhitelists();
2373 - (void)_updateActiveState
2375 if (_private && _private->page)
2376 _private->page->focusController()->setActive([[self window] isKeyWindow]);
2379 static PassOwnPtr<Vector<String> > toStringVector(NSArray* patterns)
2381 // Convert the patterns into Vectors.
2382 NSUInteger count = [patterns count];
2385 Vector<String>* patternsVector = new Vector<String>;
2386 for (NSUInteger i = 0; i < count; ++i) {
2387 id entry = [patterns objectAtIndex:i];
2388 if ([entry isKindOfClass:[NSString class]])
2389 patternsVector->append(String((NSString*)entry));
2391 return patternsVector;
2394 + (void)_addUserScriptToGroup:(NSString *)groupName world:(WebScriptWorld *)world source:(NSString *)source url:(NSURL *)url
2395 whitelist:(NSArray *)whitelist blacklist:(NSArray *)blacklist
2396 injectionTime:(WebUserScriptInjectionTime)injectionTime
2398 [WebView _addUserScriptToGroup:groupName world:world source:source url:url whitelist:whitelist blacklist:blacklist injectionTime:injectionTime injectedFrames:WebInjectInAllFrames];
2401 + (void)_addUserScriptToGroup:(NSString *)groupName world:(WebScriptWorld *)world source:(NSString *)source url:(NSURL *)url
2402 whitelist:(NSArray *)whitelist blacklist:(NSArray *)blacklist
2403 injectionTime:(WebUserScriptInjectionTime)injectionTime
2404 injectedFrames:(WebUserContentInjectedFrames)injectedFrames
2406 String group(groupName);
2407 if (group.isEmpty())
2410 PageGroup* pageGroup = PageGroup::pageGroup(group);
2414 pageGroup->addUserScriptToWorld(core(world), source, url, toStringVector(whitelist), toStringVector(blacklist),
2415 injectionTime == WebInjectAtDocumentStart ? InjectAtDocumentStart : InjectAtDocumentEnd,
2416 injectedFrames == WebInjectInAllFrames ? InjectInAllFrames : InjectInTopFrameOnly);
2419 + (void)_addUserStyleSheetToGroup:(NSString *)groupName world:(WebScriptWorld *)world source:(NSString *)source url:(NSURL *)url
2420 whitelist:(NSArray *)whitelist blacklist:(NSArray *)blacklist
2422 [WebView _addUserStyleSheetToGroup:groupName world:world source:source url:url whitelist:whitelist blacklist:blacklist injectedFrames:WebInjectInAllFrames];
2425 + (void)_addUserStyleSheetToGroup:(NSString *)groupName world:(WebScriptWorld *)world source:(NSString *)source url:(NSURL *)url
2426 whitelist:(NSArray *)whitelist blacklist:(NSArray *)blacklist
2427 injectedFrames:(WebUserContentInjectedFrames)injectedFrames
2429 String group(groupName);
2430 if (group.isEmpty())
2433 PageGroup* pageGroup = PageGroup::pageGroup(group);
2437 pageGroup->addUserStyleSheetToWorld(core(world), source, url, toStringVector(whitelist), toStringVector(blacklist), injectedFrames == WebInjectInAllFrames ? InjectInAllFrames : InjectInTopFrameOnly);
2440 + (void)_removeUserScriptFromGroup:(NSString *)groupName world:(WebScriptWorld *)world url:(NSURL *)url
2442 String group(groupName);
2443 if (group.isEmpty())
2446 PageGroup* pageGroup = PageGroup::pageGroup(group);
2450 pageGroup->removeUserScriptFromWorld(core(world), url);
2453 + (void)_removeUserStyleSheetFromGroup:(NSString *)groupName world:(WebScriptWorld *)world url:(NSURL *)url
2455 String group(groupName);
2456 if (group.isEmpty())
2459 PageGroup* pageGroup = PageGroup::pageGroup(group);
2463 pageGroup->removeUserStyleSheetFromWorld(core(world), url);
2466 + (void)_removeUserScriptsFromGroup:(NSString *)groupName world:(WebScriptWorld *)world
2468 String group(groupName);
2469 if (group.isEmpty())
2472 PageGroup* pageGroup = PageGroup::pageGroup(group);
2476 pageGroup->removeUserScriptsFromWorld(core(world));
2479 + (void)_removeUserStyleSheetsFromGroup:(NSString *)groupName world:(WebScriptWorld *)world
2481 String group(groupName);
2482 if (group.isEmpty())
2485 PageGroup* pageGroup = PageGroup::pageGroup(group);
2489 pageGroup->removeUserStyleSheetsFromWorld(core(world));
2492 + (void)_removeAllUserContentFromGroup:(NSString *)groupName
2494 String group(groupName);
2495 if (group.isEmpty())
2498 PageGroup* pageGroup = PageGroup::pageGroup(group);
2502 pageGroup->removeAllUserContent();
2505 - (BOOL)cssAnimationsSuspended
2507 return _private->cssAnimationsSuspended;
2510 - (void)setCSSAnimationsSuspended:(BOOL)suspended
2512 if (suspended == _private->cssAnimationsSuspended)
2515 _private->cssAnimationsSuspended = suspended;
2517 Frame* frame = core([self mainFrame]);
2519 frame->animation()->suspendAnimations(frame->document());
2521 frame->animation()->resumeAnimations(frame->document());
2524 + (void)_setDomainRelaxationForbidden:(BOOL)forbidden forURLScheme:(NSString *)scheme
2526 SecurityOrigin::setDomainRelaxationForbiddenForURLScheme(forbidden, scheme);
2529 + (void)_registerURLSchemeAsSecure:(NSString *)scheme
2531 SchemeRegistry::registerURLSchemeAsSecure(scheme);
2536 @implementation _WebSafeForwarder
2538 // Used to send messages to delegates that implement informal protocols.
2540 - (id)initWithTarget:(id)t defaultTarget:(id)dt catchExceptions:(BOOL)c
2542 self = [super init];
2545 target = t; // Non retained.
2547 catchExceptions = c;
2551 - (void)forwardInvocation:(NSInvocation *)invocation
2553 if ([target respondsToSelector:[invocation selector]]) {
2554 if (catchExceptions) {
2556 [invocation invokeWithTarget:target];
2557 } @catch(id exception) {
2558 ReportDiscardedDelegateException([invocation selector], exception);
2561 [invocation invokeWithTarget:target];
2565 if ([defaultTarget respondsToSelector:[invocation selector]])
2566 [invocation invokeWithTarget:defaultTarget];
2568 // Do nothing quietly if method not implemented.
2571 - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
2573 return [defaultTarget methodSignatureForSelector:aSelector];
2578 @implementation WebView
2582 static BOOL initialized = NO;
2587 InitWebCoreSystemInterface();
2588 JSC::initializeThreading();
2589 WTF::initializeMainThreadToProcessMainThread();
2591 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_applicationWillTerminate) name:NSApplicationWillTerminateNotification object:NSApp];
2592 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:) name:WebPreferencesChangedNotification object:nil];
2593 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesRemovedNotification:) name:WebPreferencesRemovedNotification object:nil];
2595 continuousSpellCheckingEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebContinuousSpellCheckingEnabled];
2596 #ifndef BUILDING_ON_TIGER
2597 grammarCheckingEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebGrammarCheckingEnabled];
2600 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
2601 automaticQuoteSubstitutionEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticQuoteSubstitutionEnabled];
2602 automaticLinkDetectionEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticLinkDetectionEnabled];
2603 automaticDashSubstitutionEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticDashSubstitutionEnabled];
2604 automaticTextReplacementEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticTextReplacementEnabled];
2605 automaticSpellingCorrectionEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticSpellingCorrectionEnabled];
2609 + (void)_applicationWillTerminate
2611 applicationIsTerminating = YES;
2613 if (fastDocumentTeardownEnabled())
2614 [self closeAllWebViews];
2616 if (!pluginDatabaseClientCount)
2617 [WebPluginDatabase closeSharedDatabase];
2619 PageGroup::closeLocalStorage();
2622 + (BOOL)_canShowMIMEType:(NSString *)MIMEType allowingPlugins:(BOOL)allowPlugins
2624 return [self _viewClass:nil andRepresentationClass:nil forMIMEType:MIMEType allowingPlugins:allowPlugins];
2627 + (BOOL)canShowMIMEType:(NSString *)MIMEType
2629 return [self _canShowMIMEType:MIMEType allowingPlugins:YES];
2632 - (BOOL)_canShowMIMEType:(NSString *)MIMEType
2634 return [[self class] _canShowMIMEType:MIMEType allowingPlugins:[_private->preferences arePlugInsEnabled]];
2637 - (WebBasePluginPackage *)_pluginForMIMEType:(NSString *)MIMEType
2639 if (![_private->preferences arePlugInsEnabled])
2642 WebBasePluginPackage *pluginPackage = [[WebPluginDatabase sharedDatabase] pluginForMIMEType:MIMEType];
2644 return pluginPackage;
2646 if (_private->pluginDatabase)
2647 return [_private->pluginDatabase pluginForMIMEType:MIMEType];
2652 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
2653 - (WebBasePluginPackage *)_videoProxyPluginForMIMEType:(NSString *)MIMEType
2655 WebBasePluginPackage *pluginPackage = [[WebPluginDatabase sharedDatabase] pluginForMIMEType:MIMEType];
2657 return pluginPackage;
2659 if (_private->pluginDatabase)
2660 return [_private->pluginDatabase pluginForMIMEType:MIMEType];
2666 - (WebBasePluginPackage *)_pluginForExtension:(NSString *)extension
2668 if (![_private->preferences arePlugInsEnabled])
2671 WebBasePluginPackage *pluginPackage = [[WebPluginDatabase sharedDatabase] pluginForExtension:extension];
2673 return pluginPackage;
2675 if (_private->pluginDatabase)
2676 return [_private->pluginDatabase pluginForExtension:extension];
2681 - (void)addPluginInstanceView:(NSView *)view
2683 if (!_private->pluginDatabase)
2684 _private->pluginDatabase = [[WebPluginDatabase alloc] init];
2685 [_private->pluginDatabase addPluginInstanceView:view];
2688 - (void)removePluginInstanceView:(NSView *)view
2690 if (_private->pluginDatabase)
2691 [_private->pluginDatabase removePluginInstanceView:view];
2694 - (void)removePluginInstanceViewsFor:(WebFrame*)webFrame
2696 if (_private->pluginDatabase)
2697 [_private->pluginDatabase removePluginInstanceViewsFor:webFrame];
2700 - (BOOL)_isMIMETypeRegisteredAsPlugin:(NSString *)MIMEType
2702 if (![_private->preferences arePlugInsEnabled])
2705 if ([[WebPluginDatabase sharedDatabase] isMIMETypeRegistered:MIMEType])
2708 if (_private->pluginDatabase && [_private->pluginDatabase isMIMETypeRegistered:MIMEType])
2714 + (BOOL)canShowMIMETypeAsHTML:(NSString *)MIMEType
2716 return [WebFrameView _canShowMIMETypeAsHTML:MIMEType];
2719 + (NSArray *)MIMETypesShownAsHTML
2721 NSMutableDictionary *viewTypes = [WebFrameView _viewTypesAllowImageTypeOmission:YES];
2722 NSEnumerator *enumerator = [viewTypes keyEnumerator];
2724 NSMutableArray *array = [[[NSMutableArray alloc] init] autorelease];
2726 while ((key = [enumerator nextObject])) {
2727 if ([viewTypes objectForKey:key] == [WebHTMLView class])
2728 [array addObject:key];
2734 + (void)setMIMETypesShownAsHTML:(NSArray *)MIMETypes
2736 NSDictionary *viewTypes = [[WebFrameView _viewTypesAllowImageTypeOmission:YES] copy];
2737 NSEnumerator *enumerator = [viewTypes keyEnumerator];
2739 while ((key = [enumerator nextObject])) {
2740 if ([viewTypes objectForKey:key] == [WebHTMLView class])
2741 [WebView _unregisterViewClassAndRepresentationClassForMIMEType:key];
2744 int i, count = [MIMETypes count];
2745 for (i = 0; i < count; i++) {
2746 [WebView registerViewClass:[WebHTMLView class]
2747 representationClass:[WebHTMLRepresentation class]
2748 forMIMEType:[MIMETypes objectAtIndex:i]];
2750 [viewTypes release];
2753 + (NSURL *)URLFromPasteboard:(NSPasteboard *)pasteboard
2755 return [pasteboard _web_bestURL];
2758 + (NSString *)URLTitleFromPasteboard:(NSPasteboard *)pasteboard
2760 return [pasteboard stringForType:WebURLNamePboardType];
2763 + (void)registerURLSchemeAsLocal:(NSString *)protocol
2765 SchemeRegistry::registerURLSchemeAsLocal(protocol);
2768 - (id)_initWithArguments:(NSDictionary *) arguments
2770 NSCoder *decoder = [arguments objectForKey:@"decoder"];
2772 self = [self initWithCoder:decoder];
2774 ASSERT([arguments objectForKey:@"frame"]);
2775 NSValue *frameValue = [arguments objectForKey:@"frame"];
2776 NSRect frame = (frameValue ? [frameValue rectValue] : NSZeroRect);
2777 NSString *frameName = [arguments objectForKey:@"frameName"];
2778 NSString *groupName = [arguments objectForKey:@"groupName"];
2779 self = [self initWithFrame:frame frameName:frameName groupName:groupName];
2785 static bool clientNeedsWebViewInitThreadWorkaround()
2787 if (WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_WEBVIEW_INIT_THREAD_WORKAROUND))
2790 NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
2793 if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.installer"])
2797 if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.Automator"])
2800 // Automator Runner.
2801 if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.AutomatorRunner"])
2804 // Automator workflows.
2805 if ([bundleIdentifier _webkit_hasCaseInsensitivePrefix:@"com.apple.Automator."])
2808 #if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
2810 if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.Mail"])
2817 static bool needsWebViewInitThreadWorkaround()
2819 static bool isOldClient = clientNeedsWebViewInitThreadWorkaround();
2820 return isOldClient && !pthread_main_np();
2823 - (id)initWithFrame:(NSRect)f
2825 return [self initWithFrame:f frameName:nil groupName:nil];
2828 - (id)initWithFrame:(NSRect)f frameName:(NSString *)frameName groupName:(NSString *)groupName
2830 if (needsWebViewInitThreadWorkaround())
2831 return [[self _webkit_invokeOnMainThread] initWithFrame:f frameName:frameName groupName:groupName];
2833 WebCoreThreadViolationCheckRoundTwo();
2834 return [self _initWithFrame:f frameName:frameName groupName:groupName usesDocumentViews:YES];
2837 - (id)initWithCoder:(NSCoder *)decoder
2839 if (needsWebViewInitThreadWorkaround())
2840 return [[self _webkit_invokeOnMainThread] initWithCoder:decoder];
2842 WebCoreThreadViolationCheckRoundTwo();
2843 WebView *result = nil;
2846 NSString *frameName;
2847 NSString *groupName;
2848 WebPreferences *preferences;
2849 BOOL useBackForwardList = NO;
2850 BOOL allowsUndo = YES;
2852 result = [super initWithCoder:decoder];
2853 result->_private = [[WebViewPrivate alloc] init];
2855 // We don't want any of the archived subviews. The subviews will always
2856 // be created in _commonInitializationFrameName:groupName:.
2857 [[result subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
2859 if ([decoder allowsKeyedCoding]) {
2860 frameName = [decoder decodeObjectForKey:@"FrameName"];
2861 groupName = [decoder decodeObjectForKey:@"GroupName"];
2862 preferences = [decoder decodeObjectForKey:@"Preferences"];
2863 useBackForwardList = [decoder decodeBoolForKey:@"UseBackForwardList"];
2864 if ([decoder containsValueForKey:@"AllowsUndo"])
2865 allowsUndo = [decoder decodeBoolForKey:@"AllowsUndo"];
2868 [decoder decodeValueOfObjCType:@encode(int) at:&version];
2869 frameName = [decoder decodeObject];
2870 groupName = [decoder decodeObject];
2871 preferences = [decoder decodeObject];
2873 [decoder decodeValuesOfObjCTypes:"c", &useBackForwardList];
2874 // The allowsUndo field is no longer written out in encodeWithCoder, but since there are
2875 // version 3 NIBs that have this field encoded, we still need to read it in.
2877 [decoder decodeValuesOfObjCTypes:"c", &allowsUndo];
2880 if (![frameName isKindOfClass:[NSString class]])
2882 if (![groupName isKindOfClass:[NSString class]])
2884 if (![preferences isKindOfClass:[WebPreferences class]])
2887 LOG(Encoding, "FrameName = %@, GroupName = %@, useBackForwardList = %d\n", frameName, groupName, (int)useBackForwardList);
2888 [result _commonInitializationWithFrameName:frameName groupName:groupName usesDocumentViews:YES];
2889 [result page]->backForwardList()->setEnabled(useBackForwardList);
2890 result->_private->allowsUndo = allowsUndo;
2892 [result setPreferences:preferences];
2893 } @catch (NSException *localException) {
2901 - (void)encodeWithCoder:(NSCoder *)encoder
2903 // Set asside the subviews before we archive. We don't want to archive any subviews.
2904 // The subviews will always be created in _commonInitializationFrameName:groupName:.
2905 id originalSubviews = _subviews;
2908 [super encodeWithCoder:encoder];
2910 // Restore the subviews we set aside.
2911 _subviews = originalSubviews;
2913 BOOL useBackForwardList = _private->page && _private->page->backForwardList()->enabled();
2914 if ([encoder allowsKeyedCoding]) {
2915 [encoder encodeObject:[[self mainFrame] name] forKey:@"FrameName"];
2916 [encoder encodeObject:[self groupName] forKey:@"GroupName"];
2917 [encoder encodeObject:[self preferences] forKey:@"Preferences"];
2918 [encoder encodeBool:useBackForwardList forKey:@"UseBackForwardList"];
2919 [encoder encodeBool:_private->allowsUndo forKey:@"AllowsUndo"];
2921 int version = WebViewVersion;
2922 [encoder encodeValueOfObjCType:@encode(int) at:&version];
2923 [encoder encodeObject:[[self mainFrame] name]];
2924 [encoder encodeObject:[self groupName]];
2925 [encoder encodeObject:[self preferences]];
2926 [encoder encodeValuesOfObjCTypes:"c", &useBackForwardList];
2927 // DO NOT encode any new fields here, doing so will break older WebKit releases.
2930 LOG(Encoding, "FrameName = %@, GroupName = %@, useBackForwardList = %d\n", [[self mainFrame] name], [self groupName], (int)useBackForwardList);
2935 if (WebCoreObjCScheduleDeallocateOnMainThread([WebView class], self))
2938 // call close to ensure we tear-down completely
2939 // this maintains our old behavior for existing applications
2942 if ([[self class] shouldIncludeInWebKitStatistics])
2945 if ([self _needsFrameLoadDelegateRetainQuirk])
2946 [_private->frameLoadDelegate release];
2949 // [super dealloc] can end up dispatching against _private (3466082)
2957 ASSERT(_private->closed);
2966 // _close existed first, and some clients might be calling or overriding it, so call through.
2970 - (void)setShouldCloseWithWindow:(BOOL)close
2972 _private->shouldCloseWithWindow = close;
2975 - (BOOL)shouldCloseWithWindow
2977 return _private->shouldCloseWithWindow;
2980 - (void)addWindowObserversForWindow:(NSWindow *)window
2983 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowDidBecomeKey:)
2984 name:NSWindowDidBecomeKeyNotification object:nil];
2985 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowDidResignKey:)
2986 name:NSWindowDidResignKeyNotification object:nil];
2987 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillOrderOnScreen:)
2988 name:WKWindowWillOrderOnScreenNotification() object:window];
2992 - (void)removeWindowObservers
2994 NSWindow *window = [self window];
2996 [[NSNotificationCenter defaultCenter] removeObserver:self
2997 name:NSWindowDidBecomeKeyNotification object:nil];
2998 [[NSNotificationCenter defaultCenter] removeObserver:self
2999 name:NSWindowDidResignKeyNotification object:nil];
3000 [[NSNotificationCenter defaultCenter] removeObserver:self
3001 name:WKWindowWillOrderOnScreenNotification() object:window];
3005 - (void)viewWillMoveToWindow:(NSWindow *)window
3007 // Don't do anything if the WebView isn't initialized.
3008 // This happens when decoding a WebView in a nib.
3009 // FIXME: What sets up the observer of NSWindowWillCloseNotification in this case?
3010 if (!_private || _private->closed)
3013 if ([self window] && [self window] != [self hostWindow])
3014 [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowWillCloseNotification object:[self window]];
3017 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillClose:) name:NSWindowWillCloseNotification object:window];
3019 // Ensure that we will receive the events that WebHTMLView (at least) needs.
3020 // The following are expensive enough that we don't want to call them over
3021 // and over, so do them when we move into a window.
3022 [window setAcceptsMouseMovedEvents:YES];
3023 WKSetNSWindowShouldPostEventNotifications(window, YES);
3025 _private->page->setCanStartMedia(false);
3026 _private->page->willMoveOffscreen();
3029 if (window != [self window]) {
3030 [self removeWindowObservers];
3031 [self addWindowObserversForWindow:window];
3035 - (void)viewDidMoveToWindow
3037 // Don't do anything if we aren't initialized. This happens
3038 // when decoding a WebView. When WebViews are decoded their subviews
3039 // are created by initWithCoder: and so won't be normally
3040 // initialized. The stub views are discarded by WebView.
3041 if (!_private || _private->closed)
3044 if ([self window]) {
3045 _private->page->setCanStartMedia(true);
3046 _private->page->didMoveOnscreen();
3049 [self _updateActiveState];
3052 - (void)_windowDidBecomeKey:(NSNotification *)notification
3054 NSWindow *keyWindow = [notification object];
3055 if (keyWindow == [self window] || keyWindow == [[self window] attachedSheet])
3056 [self _updateActiveState];
3059 - (void)_windowDidResignKey:(NSNotification *)notification
3061 NSWindow *formerKeyWindow = [notification object];
3062 if (formerKeyWindow == [self window] || formerKeyWindow == [[self window] attachedSheet])
3063 [self _updateActiveState];
3066 - (void)_windowWillOrderOnScreen:(NSNotification *)notification
3068 if (![self shouldUpdateWhileOffscreen])
3069 [self setNeedsDisplay:YES];
3072 - (void)_windowWillClose:(NSNotification *)notification
3074 if ([self shouldCloseWithWindow] && ([self window] == [self hostWindow] || ([self window] && ![self hostWindow]) || (![self window] && [self hostWindow])))
3078 - (void)setPreferences:(WebPreferences *)prefs
3081 prefs = [WebPreferences standardPreferences];
3083 if (_private->preferences == prefs)
3086 [prefs willAddToWebView];
3088 WebPreferences *oldPrefs = _private->preferences;
3090 [[NSNotificationCenter defaultCenter] removeObserver:self name:WebPreferencesChangedNotification object:[self preferences]];
3091 [WebPreferences _removeReferenceForIdentifier:[oldPrefs identifier]];
3093 _private->preferences = [prefs retain];
3095 // After registering for the notification, post it so the WebCore settings update.
3096 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:)
3097 name:WebPreferencesChangedNotification object:[self preferences]];
3098 [[self preferences] _postPreferencesChangesNotification];
3100 [oldPrefs didRemoveFromWebView];
3104 - (WebPreferences *)preferences
3106 return _private->preferences;
3109 - (void)setPreferencesIdentifier:(NSString *)anIdentifier
3111 if (!_private->closed && ![anIdentifier isEqual:[[self preferences] identifier]]) {
3112 WebPreferences *prefs = [[WebPreferences alloc] initWithIdentifier:anIdentifier];
3113 [self setPreferences:prefs];
3118 - (NSString *)preferencesIdentifier
3120 return [[self preferences] identifier];
3124 - (void)setUIDelegate:delegate
3126 _private->UIDelegate = delegate;
3127 [_private->UIDelegateForwarder release];
3128 _private->UIDelegateForwarder = nil;
3133 return _private->UIDelegate;
3136 - (void)setResourceLoadDelegate: delegate
3138 _private->resourceProgressDelegate = delegate;
3139 [self _cacheResourceLoadDelegateImplementations];
3142 - (id)resourceLoadDelegate
3144 return _private->resourceProgressDelegate;
3147 - (void)setDownloadDelegate: delegate
3149 _private->downloadDelegate = delegate;
3153 - (id)downloadDelegate
3155 return _private->downloadDelegate;
3158 - (void)setPolicyDelegate:delegate
3160 _private->policyDelegate = delegate;
3161 [_private->policyDelegateForwarder release];
3162 _private->policyDelegateForwarder = nil;
3165 - (id)policyDelegate
3167 return _private->policyDelegate;
3170 - (void)setFrameLoadDelegate:delegate
3172 // <rdar://problem/6950660> - Due to some subtle WebKit changes - presumably to delegate callback behavior - we've
3173 // unconvered a latent bug in at least one WebKit app where the delegate wasn't properly retained by the app and
3174 // was dealloc'ed before being cleared.
3175 // This is an effort to keep such apps working for now.
3176 if ([self _needsFrameLoadDelegateRetainQuirk]) {
3178 [_private->frameLoadDelegate release];
3181 _private->frameLoadDelegate = delegate;
3182 [self _cacheFrameLoadDelegateImplementations];
3184 #if ENABLE(ICONDATABASE)
3185 // If this delegate wants callbacks for icons, fire up the icon database.
3186 if (_private->frameLoadDelegateImplementations.didReceiveIconForFrameFunc)
3187 [WebIconDatabase sharedIconDatabase];
3191 - (id)frameLoadDelegate
3193 return _private->frameLoadDelegate;
3196 - (WebFrame *)mainFrame
3198 // This can be called in initialization, before _private has been set up (3465613)
3199 if (!_private || !_private->page)
3201 return kit(_private->page->mainFrame());
3204 - (WebFrame *)selectedFrame
3206 if (_private->usesDocumentViews) {
3207 // If the first responder is a view in our tree, we get the frame containing the first responder.
3208 // This is faster than searching the frame hierarchy, and will give us a result even in the case
3209 // where the focused frame doesn't actually contain a selection.
3210 WebFrame *focusedFrame = [self _focusedFrame];
3212 return focusedFrame;
3215 // If the first responder is outside of our view tree, we search for a frame containing a selection.
3216 // There should be at most only one of these.
3217 return [[self mainFrame] _findFrameWithSelection];
3220 - (WebBackForwardList *)backForwardList
3222 if (!_private->page)
3224 if (!_private->page->backForwardList()->enabled())
3226 return kit(_private->page->backForwardList());
3229 - (void)setMaintainsBackForwardList:(BOOL)flag
3231 if (!_private->page)
3233 _private->page->backForwardList()->setEnabled(flag);
3238 if (!_private->page)
3241 return _private->page->goBack();
3246 if (!_private->page)
3249 return _private->page->goForward();
3252 - (BOOL)goToBackForwardItem:(WebHistoryItem *)item
3254 if (!_private->page)
3257 _private->page->goToItem(core(item), FrameLoadTypeIndexedBackForward);
3261 - (void)setTextSizeMultiplier:(float)m
3263 [self _setZoomMultiplier:m isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3266 - (float)textSizeMultiplier
3268 return [self _realZoomMultiplierIsTextOnly] ? _private->zoomMultiplier : 1.0f;
3271 - (void)_setZoomMultiplier:(float)multiplier isTextOnly:(BOOL)isTextOnly
3273 // NOTE: This has no visible effect when viewing a PDF (see <rdar://problem/4737380>)
3274 _private->zoomMultiplier = multiplier;
3276 ASSERT(_private->page);
3278 _private->page->settings()->setZoomMode(isTextOnly ? ZoomTextOnly : ZoomPage);
3280 // FIXME: It would be nice to rework this code so that _private->zoomMultiplier doesn't exist
3281 // and instead FrameView::zoomFactor is used.
3282 Frame* coreFrame = [self _mainCoreFrame];
3284 if (FrameView* view = coreFrame->view())
3285 view->setZoomFactor(multiplier, isTextOnly ? ZoomTextOnly : ZoomPage);
3289 - (float)_zoomMultiplier:(BOOL)isTextOnly
3291 if (isTextOnly != [self _realZoomMultiplierIsTextOnly])
3293 return _private->zoomMultiplier;
3296 - (float)_realZoomMultiplier
3298 return _private->zoomMultiplier;
3301 - (BOOL)_realZoomMultiplierIsTextOnly
3303 if (!_private->page)
3306 return _private->page->settings()->zoomMode() == ZoomTextOnly;
3309 #define MinimumZoomMultiplier 0.5f
3310 #define MaximumZoomMultiplier 3.0f
3311 #define ZoomMultiplierRatio 1.2f
3313 - (BOOL)_canZoomOut:(BOOL)isTextOnly
3315 id docView = [[[self mainFrame] frameView] documentView];
3316 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
3317 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
3318 return [zoomingDocView _canZoomOut];
3320 return [self _zoomMultiplier:isTextOnly] / ZoomMultiplierRatio > MinimumZoomMultiplier;
3324 - (BOOL)_canZoomIn:(BOOL)isTextOnly
3326 id docView = [[[self mainFrame] frameView] documentView];
3327 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
3328 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
3329 return [zoomingDocView _canZoomIn];
3331 return [self _zoomMultiplier:isTextOnly] * ZoomMultiplierRatio < MaximumZoomMultiplier;
3334 - (IBAction)_zoomOut:(id)sender isTextOnly:(BOOL)isTextOnly
3336 id docView = [[[self mainFrame] frameView] documentView];
3337 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
3338 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
3339 return [zoomingDocView _zoomOut:sender];
3341 float newScale = [self _zoomMultiplier:isTextOnly] / ZoomMultiplierRatio;
3342 if (newScale > MinimumZoomMultiplier)
3343 [self _setZoomMultiplier:newScale isTextOnly:isTextOnly];
3346 - (IBAction)_zoomIn:(id)sender isTextOnly:(BOOL)isTextOnly
3348 id docView = [[[self mainFrame] frameView] documentView];
3349 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
3350 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
3351 return [zoomingDocView _zoomIn:sender];
3353 float newScale = [self _zoomMultiplier:isTextOnly] * ZoomMultiplierRatio;
3354 if (newScale < MaximumZoomMultiplier)
3355 [self _setZoomMultiplier:newScale isTextOnly:isTextOnly];
3358 - (BOOL)_canResetZoom:(BOOL)isTextOnly
3360 id docView = [[[self mainFrame] frameView] documentView];
3361 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
3362 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
3363 return [zoomingDocView _canResetZoom];
3365 return [self _zoomMultiplier:isTextOnly] != 1.0f;
3368 - (IBAction)_resetZoom:(id)sender isTextOnly:(BOOL)isTextOnly
3370 id docView = [[[self mainFrame] frameView] documentView];
3371 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
3372 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
3373 return [zoomingDocView _resetZoom:sender];
3375 if ([self _zoomMultiplier:isTextOnly] != 1.0f)
3376 [self _setZoomMultiplier:1.0f isTextOnly:isTextOnly];
3379 - (void)setApplicationNameForUserAgent:(NSString *)applicationName
3381 NSString *name = [applicationName copy];
3382 [_private->applicationNameForUserAgent release];
3383 _private->applicationNameForUserAgent = name;
3384 if (!_private->userAgentOverridden)
3385 _private->userAgent = String();
3388 - (NSString *)applicationNameForUserAgent
3390 return [[_private->applicationNameForUserAgent retain] autorelease];
3393 - (void)setCustomUserAgent:(NSString *)userAgentString
3395 _private->userAgent = userAgentString;
3396 _private->userAgentOverridden = userAgentString != nil;
3399 - (NSString *)customUserAgent
3401 if (!_private->userAgentOverridden)
3403 return _private->userAgent;
3406 - (void)setMediaStyle:(NSString *)mediaStyle
3408 if (_private->mediaStyle != mediaStyle) {
3409 [_private->mediaStyle release];
3410 _private->mediaStyle = [mediaStyle copy];
3414 - (NSString *)mediaStyle
3416 return _private->mediaStyle;
3419 - (BOOL)supportsTextEncoding
3421 id documentView = [[[self mainFrame] frameView] documentView];
3422 return [documentView conformsToProtocol:@protocol(WebDocumentText)]
3423 && [documentView supportsTextEncoding];
3426 - (void)setCustomTextEncodingName:(NSString *)encoding
3428 NSString *oldEncoding = [self customTextEncodingName];
3429 if (encoding == oldEncoding || [encoding isEqualToString:oldEncoding])
3431 if (Frame* mainFrame = [self _mainCoreFrame])
3432 mainFrame->loader()->reloadWithOverrideEncoding(encoding);
3435 - (NSString *)_mainFrameOverrideEncoding
3437 WebDataSource *dataSource = [[self mainFrame] provisionalDataSource];
3438 if (dataSource == nil)
3439 dataSource = [[self mainFrame] _dataSource];
3440 if (dataSource == nil)
3442 return nsStringNilIfEmpty([dataSource _documentLoader]->overrideEncoding());
3445 - (NSString *)customTextEncodingName
3447 return [self _mainFrameOverrideEncoding];
3450 - (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script
3452 // Return statements are only valid in a function but some applications pass in scripts
3453 // prefixed with return (<rdar://problems/5103720&4616860>) since older WebKit versions
3454 // silently ignored the return. If the application is linked against an earlier version
3455 // of WebKit we will strip the return so the script wont fail.
3456 if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_JAVASCRIPT_RETURN_QUIRK)) {
3457 NSRange returnStringRange = [script rangeOfString:@"return "];
3458 if (returnStringRange.length && !returnStringRange.location)
3459 script = [script substringFromIndex:returnStringRange.location + returnStringRange.length];
3462 NSString *result = [[self mainFrame] _stringByEvaluatingJavaScriptFromString:script];
3463 // The only way stringByEvaluatingJavaScriptFromString can return nil is if the frame was removed by the script
3464 // Since there's no way to get rid of the main frame, result will never ever be nil here.
3470 - (WebScriptObject *)windowScriptObject
3472 Frame* coreFrame = [self _mainCoreFrame];
3475 return coreFrame->script()->windowScriptObject();
3478 // Get the appropriate user-agent string for a particular URL.
3479 - (NSString *)userAgentForURL:(NSURL *)url
3481 if (_private->useSiteSpecificSpoofing) {
3482 // No current site-specific spoofs.
3485 if (_private->userAgent.isNull())
3486 _private->userAgent = [[self class] _standardUserAgentWithApplicationName:_private->applicationNameForUserAgent];
3488 return _private->userAgent;
3491 - (void)setHostWindow:(NSWindow *)hostWindow
3493 if (_private->closed && hostWindow)
3495 if (hostWindow == _private->hostWindow)
3498 Frame* coreFrame = [self _mainCoreFrame];
3499 if (_private->usesDocumentViews) {
3500 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
3501 [[[kit(frame) frameView] documentView] viewWillMoveToHostWindow:hostWindow];
3503 if (_private->hostWindow && [self window] != _private->hostWindow)
3504 [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowWillCloseNotification object:_private->hostWindow];
3506 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillClose:) name:NSWindowWillCloseNotification object:hostWindow];
3507 [_private->hostWindow release];
3508 _private->hostWindow = [hostWindow retain];
3509 if (_private->usesDocumentViews) {
3510 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
3511 [[[kit(frame) frameView] documentView] viewDidMoveToHostWindow];
3515 - (NSWindow *)hostWindow
3517 // -[WebView hostWindow] can sometimes be called from the WebView's [super dealloc] method
3518 // so we check here to make sure it's not null.
3522 return _private->hostWindow;
3525 - (NSView <WebDocumentView> *)documentViewAtWindowPoint:(NSPoint)point
3527 return [[self _frameViewAtWindowPoint:point] documentView];
3530 - (NSDictionary *)_elementAtWindowPoint:(NSPoint)windowPoint
3532 WebFrameView *frameView = [self _frameViewAtWindowPoint:windowPoint];
3535 NSView <WebDocumentView> *documentView = [frameView documentView];
3536 if ([documentView conformsToProtocol:@protocol(WebDocumentElement)]) {
3537 NSPoint point = [documentView convertPoint:windowPoint fromView:nil];
3538 return [(NSView <WebDocumentElement> *)documentView elementAtPoint:point];
3540 return [NSDictionary dictionaryWithObject:[frameView webFrame] forKey:WebElementFrameKey];
3543 - (NSDictionary *)elementAtPoint:(NSPoint)point
3545 return [self _elementAtWindowPoint:[self convertPoint:point toView:nil]];
3548 // The following 2 internal NSView methods are called on the drag destination to make scrolling while dragging work.
3549 // Scrolling while dragging will only work if the drag destination is in a scroll view. The WebView is the drag destination.
3550 // When dragging to a WebView, the document subview should scroll, but it doesn't because it is not the drag destination.
3551 // Forward these calls to the document subview to make its scroll view scroll.
3552 - (void)_autoscrollForDraggingInfo:(id)draggingInfo timeDelta:(NSTimeInterval)repeatDelta
3554 NSView <WebDocumentView> *documentView = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3555 [documentView _autoscrollForDraggingInfo:draggingInfo timeDelta:repeatDelta];
3558 - (BOOL)_shouldAutoscrollForDraggingInfo:(id)draggingInfo
3560 NSView <WebDocumentView> *documentView = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3561 return [documentView _shouldAutoscrollForDraggingInfo:draggingInfo];
3564 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)draggingInfo
3566 NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3567 WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]] ? (WebHTMLView*)view : nil);
3568 IntPoint client([draggingInfo draggingLocation]);
3569 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
3570 DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
3571 return core(self)->dragController()->dragEntered(&dragData);
3574 - (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)draggingInfo
3576 Page* page = core(self);
3578 return NSDragOperationNone;
3580 NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3581 WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]] ? (WebHTMLView*)view : nil);
3582 IntPoint client([draggingInfo draggingLocation]);
3583 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
3584 DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
3585 return page->dragController()->dragUpdated(&dragData);
3588 - (void)draggingExited:(id <NSDraggingInfo>)draggingInfo
3590 Page* page = core(self);
3594 NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3595 WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]] ? (WebHTMLView*)view : nil);
3596 IntPoint client([draggingInfo draggingLocation]);
3597 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
3598 DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
3599 page->dragController()->dragExited(&dragData);
3602 - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)draggingInfo
3607 - (BOOL)performDragOperation:(id <NSDraggingInfo>)draggingInfo
3609 NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3610 WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]]? (WebHTMLView*)view : nil);
3611 IntPoint client([draggingInfo draggingLocation]);
3612 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
3613 DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
3614 return core(self)->dragController()->performDrag(&dragData);
3617 - (NSView *)_hitTest:(NSPoint *)point dragTypes:(NSSet *)types
3619 NSView *hitView = [super _hitTest:point dragTypes:types];
3620 if (!hitView && [[self superview] mouse:*point inRect:[self frame]])
3625 - (BOOL)acceptsFirstResponder
3627 if (_private->usesDocumentViews)
3628 return [[[self mainFrame] frameView] acceptsFirstResponder];
3630 // FIXME (Viewless): Need more code from WebHTMLView here.
3634 - (BOOL)becomeFirstResponder
3636 if (_private->usesDocumentViews) {
3637 if (_private->becomingFirstResponder) {
3638 // Fix for unrepro infinite recursion reported in Radar 4448181. If we hit this assert on
3639 // a debug build, we should figure out what causes the problem and do a better fix.
3640 ASSERT_NOT_REACHED();
3644 // This works together with setNextKeyView to splice the WebView into
3645 // the key loop similar to the way NSScrollView does this. Note that
3646 // WebFrameView has very similar code.
3647 NSWindow *window = [self window];
3648 WebFrameView *mainFrameView = [[self mainFrame] frameView];
3650 NSResponder *previousFirstResponder = [[self window] _oldFirstResponderBeforeBecoming];
3651 BOOL fromOutside = ![previousFirstResponder isKindOfClass:[NSView class]] || (![(NSView *)previousFirstResponder isDescendantOf:self] && previousFirstResponder != self);
3653 if ([window keyViewSelectionDirection] == NSSelectingPrevious) {
3654 NSView *previousValidKeyView = [self previousValidKeyView];
3655 if (previousValidKeyView != self && previousValidKeyView != mainFrameView) {
3656 _private->becomingFirstResponder = YES;
3657 _private->becomingFirstResponderFromOutside = fromOutside;
3658 [window makeFirstResponder:previousValidKeyView];
3659 _private->becomingFirstResponderFromOutside = NO;
3660 _private->becomingFirstResponder = NO;
3666 if ([mainFrameView acceptsFirstResponder]) {
3667 _private->becomingFirstResponder = YES;
3668 _private->becomingFirstResponderFromOutside = fromOutside;
3669 [window makeFirstResponder:mainFrameView];
3670 _private->becomingFirstResponderFromOutside = NO;
3671 _private->becomingFirstResponder = NO;
3678 // FIXME (Viewless): Need more code from WebHTMLView here.
3682 - (NSView *)_webcore_effectiveFirstResponder
3684 if (_private && _private->usesDocumentViews) {
3685 if (WebFrameView *frameView = [[self mainFrame] frameView])
3686 return [frameView _webcore_effectiveFirstResponder];
3688 return [super _webcore_effectiveFirstResponder];
3691 - (void)setNextKeyView:(NSView *)view
3693 if (_private && _private->usesDocumentViews) {
3694 // This works together with becomeFirstResponder to splice the WebView into
3695 // the key loop similar to the way NSScrollView does this. Note that
3696 // WebFrameView has similar code.
3697 if (WebFrameView *mainFrameView = [[self mainFrame] frameView]) {
3698 [mainFrameView setNextKeyView:view];
3703 [super setNextKeyView:view];
3706 static WebFrame *incrementFrame(WebFrame *frame, BOOL forward, BOOL wrapFlag)
3708 Frame* coreFrame = core(frame);
3710 ? coreFrame->tree()->traverseNextWithWrap(wrapFlag)
3711 : coreFrame->tree()->traversePreviousWithWrap(wrapFlag));
3714 - (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag
3716 return [self searchFor:string direction:forward caseSensitive:caseFlag wrap:wrapFlag startInSelection:NO];
3719 + (void)registerViewClass:(Class)viewClass representationClass:(Class)representationClass forMIMEType:(NSString *)MIMEType
3721 [[WebFrameView _viewTypesAllowImageTypeOmission:YES] setObject:viewClass forKey:MIMEType];
3722 [[WebDataSource _repTypesAllowImageTypeOmission:YES] setObject:representationClass forKey:MIMEType];
3724 // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
3725 // in the WebCore MIMEType registry. For now we're doing this in a safe, limited manner
3726 // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
3727 if ([viewClass class] == [WebHTMLView class])
3728 MIMETypeRegistry::getSupportedNonImageMIMETypes().add(MIMEType);
3731 - (void)setGroupName:(NSString *)groupName
3733 if (!_private->page)
3735 _private->page->setGroupName(groupName);
3738 - (NSString *)groupName
3740 if (!_private->page)
3742 return _private->page->groupName();
3745 - (double)estimatedProgress
3747 if (!_private->page)
3749 return _private->page->progress()->estimatedProgress();
3752 - (NSArray *)pasteboardTypesForSelection
3754 NSView <WebDocumentView> *documentView = [[[self _selectedOrMainFrame] frameView] documentView];
3755 if ([documentView conformsToProtocol:@protocol(WebDocumentSelection)]) {
3756 return [(NSView <WebDocumentSelection> *)documentView pasteboardTypesForSelection];
3758 return [NSArray array];
3761 - (void)writeSelectionWithPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
3763 WebFrame *frame = [self _selectedOrMainFrame];
3764 if (frame && [frame _hasSelection]) {
3765 NSView <WebDocumentView> *documentView = [[frame frameView] documentView];
3766 if ([documentView conformsToProtocol:@protocol(WebDocumentSelection)])
3767 [(NSView <WebDocumentSelection> *)documentView writeSelectionWithPasteboardTypes:types toPasteboard:pasteboard];
3771 - (NSArray *)pasteboardTypesForElement:(NSDictionary *)element
3773 if ([element objectForKey:WebElementImageURLKey] != nil) {
3774 return [NSPasteboard _web_writableTypesForImageIncludingArchive:([element objectForKey:WebElementDOMNodeKey] != nil)];
3775 } else if ([element objectForKey:WebElementLinkURLKey] != nil) {
3776 return [NSPasteboard _web_writableTypesForURL];
3777 } else if ([[element objectForKey:WebElementIsSelectedKey] boolValue]) {
3778 return [self pasteboardTypesForSelection];
3780 return [NSArray array];
3783 - (void)writeElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
3785 if ([element objectForKey:WebElementImageURLKey] != nil) {
3786 [self _writeImageForElement:element withPasteboardTypes:types toPasteboard:pasteboard];
3787 } else if ([element objectForKey:WebElementLinkURLKey] != nil) {
3788 [self _writeLinkElement:element withPasteboardTypes:types toPasteboard:pasteboard];
3789 } else if ([[element objectForKey:WebElementIsSelectedKey] boolValue]) {
3790 [self writeSelectionWithPasteboardTypes:types toPasteboard:pasteboard];
3794 - (void)moveDragCaretToPoint:(NSPoint)point
3796 if (Page* page = core(self))
3797 page->dragController()->placeDragCaret(IntPoint([self convertPoint:point toView:nil]));
3800 - (void)removeDragCaret
3802 if (Page* page = core(self))
3803 page->dragController()->dragEnded();
3806 - (void)setMainFrameURL:(NSString *)URLString
3808 [[self mainFrame] loadRequest: [NSURLRequest requestWithURL: [NSURL _web_URLWithDataAsString: URLString]]];
3811 - (NSString *)mainFrameURL
3814 ds = [[self mainFrame] provisionalDataSource];
3816 ds = [[self mainFrame] _dataSource];
3817 return [[[ds request] URL] _web_originalDataAsString];
3822 LOG (Bindings, "isLoading = %d", (int)[self _isLoading]);
3823 return [self _isLoading];
3826 - (NSString *)mainFrameTitle
3828 NSString *mainFrameTitle = [[[self mainFrame] _dataSource] pageTitle];
3829 return (mainFrameTitle != nil) ? mainFrameTitle : (NSString *)@"";
3832 - (NSImage *)mainFrameIcon
3834 return [[WebIconDatabase sharedIconDatabase] iconForURL:[[[[self mainFrame] _dataSource] _URL] _web_originalDataAsString] withSize:WebIconSmallSize];
3837 - (DOMDocument *)mainFrameDocument
3839 // only return the actual value if the state we're in gives NSTreeController
3840 // enough time to release its observers on the old model
3841 if (_private->mainFrameDocumentReady)
3842 return [[self mainFrame] DOMDocument];
3846 - (void)setDrawsBackground:(BOOL)drawsBackground
3848 if (_private->drawsBackground == drawsBackground)
3850 _private->drawsBackground = drawsBackground;
3851 [[self mainFrame] _updateBackgroundAndUpdatesWhileOffscreen];
3854 - (BOOL)drawsBackground
3856 // This method can be called beneath -[NSView dealloc] after we have cleared _private,
3857 // indirectly via -[WebFrameView viewDidMoveToWindow].
3858 return !_private || _private->drawsBackground;
3861 - (void)setShouldUpdateWhileOffscreen:(BOOL)updateWhileOffscreen
3863 if (_private->shouldUpdateWhileOffscreen == updateWhileOffscreen)
3865 _private->shouldUpdateWhileOffscreen = updateWhileOffscreen;
3866 [[self mainFrame] _updateBackgroundAndUpdatesWhileOffscreen];
3869 - (BOOL)shouldUpdateWhileOffscreen
3871 return _private->shouldUpdateWhileOffscreen;
3874 - (void)setCurrentNodeHighlight:(WebNodeHighlight *)nodeHighlight
3876 id old = _private->currentNodeHighlight;
3877 _private->currentNodeHighlight = [nodeHighlight retain];
3881 - (WebNodeHighlight *)currentNodeHighlight
3883 return _private->currentNodeHighlight;
3886 - (NSView *)previousValidKeyView
3888 NSView *result = [super previousValidKeyView];
3890 // Work around AppKit bug 6905484. If the result is a view that's inside this one, it's
3891 // possible it is the wrong answer, because the fact that it's a descendant causes the
3892 // code that implements key view redirection to fail; this means we won't redirect to
3893 // the toolbar, for example, when we hit the edge of a window. Since the bug is specific
3894 // to cases where the receiver of previousValidKeyView is an ancestor of the last valid
3895 // key view in the loop, we can sidestep it by walking along previous key views until
3896 // we find one that is not a superview, then using that to call previousValidKeyView.
3898 if (![result isDescendantOf:self])
3901 // Use a visited set so we don't loop indefinitely when walking crazy key loops.
3902 // AppKit uses such sets internally and we want our loop to be as robust as its loops.
3903 RetainPtr<CFMutableSetRef> visitedViews = CFSetCreateMutable(0, 0, 0);
3904 CFSetAddValue(visitedViews.get(), result);
3906 NSView *previousView = self;
3908 CFSetAddValue(visitedViews.get(), previousView);
3909 previousView = [previousView previousKeyView];
3910 if (!previousView || CFSetGetValue(visitedViews.get(), previousView))
3912 } while ([result isDescendantOf:previousView]);
3913 return [previousView previousValidKeyView];
3918 @implementation WebView (WebIBActions)
3920 - (IBAction)takeStringURLFrom: sender
3922 NSString *URLString = [sender stringValue];
3924 [[self mainFrame] loadRequest: [NSURLRequest requestWithURL: [NSURL _web_URLWithDataAsString: URLString]]];
3929 if (!_private->page || _private->page->defersLoading())
3932 return !!_private->page->backForwardList()->backItem();
3935 - (BOOL)canGoForward
3937 if (!_private->page || _private->page->defersLoading())
3940 return !!_private->page->backForwardList()->forwardItem();
3943 - (IBAction)goBack:(id)sender
3948 - (IBAction)goForward:(id)sender
3953 - (IBAction)stopLoading:(id)sender
3955 [[self mainFrame] stopLoading];
3958 - (IBAction)reload:(id)sender
3960 [[self mainFrame] reload];
3963 - (IBAction)reloadFromOrigin:(id)sender
3965 [[self mainFrame] reloadFromOrigin];
3968 // FIXME: This code should move into WebCore so that it is not duplicated in each WebKit.
3969 // (This includes canMakeTextSmaller/Larger, makeTextSmaller/Larger, and canMakeTextStandardSize/makeTextStandardSize)
3970 - (BOOL)canMakeTextSmaller
3972 return [self _canZoomOut:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3975 - (IBAction)makeTextSmaller:(id)sender
3977 return [self _zoomOut:sender isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3980 - (BOOL)canMakeTextLarger
3982 return [self _canZoomIn:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3985 - (IBAction)makeTextLarger:(id)sender
3987 return [self _zoomIn:sender isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3990 - (BOOL)canMakeTextStandardSize
3992 return [self _canResetZoom:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3995 - (IBAction)makeTextStandardSize:(id)sender
3997 return [self _resetZoom:sender isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
4000 - (IBAction)toggleSmartInsertDelete:(id)sender
4002 [self setSmartInsertDeleteEnabled:![self smartInsertDeleteEnabled]];
4005 - (IBAction)toggleContinuousSpellChecking:(id)sender
4007 [self setContinuousSpellCheckingEnabled:![self isContinuousSpellCheckingEnabled]];
4010 - (BOOL)_responderValidateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item
4012 id responder = [self _responderForResponderOperations];
4013 if (responder != self && [responder respondsToSelector:[item action]]) {
4014 if ([responder respondsToSelector:@selector(validateUserInterfaceItemWithoutDelegate:)])
4015 return [responder validateUserInterfaceItemWithoutDelegate:item];
4016 if ([responder respondsToSelector:@selector(validateUserInterfaceItem:)])
4017 return [responder validateUserInterfaceItem:item];
4023 #define VALIDATE(name) \
4024 else if (action == @selector(name:)) { return [self _responderValidateUserInterfaceItem:item]; }
4026 - (BOOL)validateUserInterfaceItemWithoutDelegate:(id <NSValidatedUserInterfaceItem>)item
4028 SEL action = [item action];
4030 if (action == @selector(goBack:)) {
4031 return [self canGoBack];
4032 } else if (action == @selector(goForward:)) {
4033 return [self canGoForward];
4034 } else if (action == @selector(makeTextLarger:)) {
4035 return [self canMakeTextLarger];
4036 } else if (action == @selector(makeTextSmaller:)) {
4037 return [self canMakeTextSmaller];
4038 } else if (action == @selector(makeTextStandardSize:)) {
4039 return [self canMakeTextStandardSize];
4040 } else if (action == @selector(reload:)) {
4041 return [[self mainFrame] _dataSource] != nil;
4042 } else if (action == @selector(stopLoading:)) {
4043 return [self _isLoading];
4044 } else if (action == @selector(toggleContinuousSpellChecking:)) {
4045 BOOL checkMark = NO;
4047 if ([self _continuousCheckingAllowed]) {
4048 checkMark = [self isContinuousSpellCheckingEnabled];
4051 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
4052 NSMenuItem *menuItem = (NSMenuItem *)item;
4053 [menuItem setState:checkMark ? NSOnState : NSOffState];
4056 } else if (action == @selector(toggleSmartInsertDelete:)) {
4057 BOOL checkMark = [self smartInsertDeleteEnabled];
4058 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
4059 NSMenuItem *menuItem = (NSMenuItem *)item;
4060 [menuItem setState:checkMark ? NSOnState : NSOffState];
4063 #ifndef BUILDING_ON_TIGER
4064 } else if (action == @selector(toggleGrammarChecking:)) {
4065 BOOL checkMark = [self isGrammarCheckingEnabled];
4066 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
4067 NSMenuItem *menuItem = (NSMenuItem *)item;
4068 [menuItem setState:checkMark ? NSOnState : NSOffState];
4072 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
4073 } else if (action == @selector(toggleAutomaticQuoteSubstitution:)) {
4074 BOOL checkMark = [self isAutomaticQuoteSubstitutionEnabled];
4075 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
4076 NSMenuItem *menuItem = (NSMenuItem *)item;
4077 [menuItem setState:checkMark ? NSOnState : NSOffState];
4080 } else if (action == @selector(toggleAutomaticLinkDetection:)) {
4081 BOOL checkMark = [self isAutomaticLinkDetectionEnabled];
4082 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
4083 NSMenuItem *menuItem = (NSMenuItem *)item;
4084 [menuItem setState:checkMark ? NSOnState : NSOffState];
4087 } else if (action == @selector(toggleAutomaticDashSubstitution:)) {
4088 BOOL checkMark = [self isAutomaticDashSubstitutionEnabled];
4089 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
4090 NSMenuItem *menuItem = (NSMenuItem *)item;
4091 [menuItem setState:checkMark ? NSOnState : NSOffState];
4094 } else if (action == @selector(toggleAutomaticTextReplacement:)) {
4095 BOOL checkMark = [self isAutomaticTextReplacementEnabled];
4096 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
4097 NSMenuItem *menuItem = (NSMenuItem *)item;
4098 [menuItem setState:checkMark ? NSOnState : NSOffState];
4101 } else if (action == @selector(toggleAutomaticSpellingCorrection:)) {
4102 BOOL checkMark = [self isAutomaticSpellingCorrectionEnabled];
4103 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
4104 NSMenuItem *menuItem = (NSMenuItem *)item;
4105 [menuItem setState:checkMark ? NSOnState : NSOffState];
4110 FOR_EACH_RESPONDER_SELECTOR(VALIDATE)
4115 - (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item
4117 BOOL result = [self validateUserInterfaceItemWithoutDelegate:item];
4118 return CallUIDelegateReturningBoolean(result, self, @selector(webView:validateUserInterfaceItem:defaultValidation:), item, result);
4123 @implementation WebView (WebPendingPublic)
4125 - (void)scheduleInRunLoop:(NSRunLoop *)runLoop forMode:(NSString *)mode
4127 if (runLoop && mode)
4128 core(self)->addSchedulePair(SchedulePair::create(runLoop, (CFStringRef)mode));
4131 - (void)unscheduleFromRunLoop:(NSRunLoop *)runLoop forMode:(NSString *)mode
4133 if (runLoop && mode)
4134 core(self)->removeSchedulePair(SchedulePair::create(runLoop, (CFStringRef)mode));
4137 - (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag startInSelection:(BOOL)startInSelection
4139 if (_private->closed)
4142 // Get the frame holding the selection, or start with the main frame
4143 WebFrame *startFrame = [self _selectedOrMainFrame];
4145 // Search the first frame, then all the other frames, in order
4146 NSView <WebDocumentSearching> *startSearchView = nil;
4147 WebFrame *frame = startFrame;
4149 WebFrame *nextFrame = incrementFrame(frame, forward, wrapFlag);
4151 BOOL onlyOneFrame = (frame == nextFrame);
4152 ASSERT(!onlyOneFrame || frame == startFrame);
4154 id <WebDocumentView> view = [[frame frameView] documentView];
4155 if ([view conformsToProtocol:@protocol(WebDocumentSearching)]) {
4156 NSView <WebDocumentSearching> *searchView = (NSView <WebDocumentSearching> *)view;
4158 if (frame == startFrame)
4159 startSearchView = searchView;
4162 // In some cases we have to search some content twice; see comment later in this method.
4163 // We can avoid ever doing this in the common one-frame case by passing YES for wrapFlag
4164 // here, and then bailing out before we get to the code that would search again in the
4166 BOOL wrapOnThisPass = wrapFlag && onlyOneFrame;
4167 if ([searchView conformsToProtocol:@protocol(WebDocumentIncrementalSearching)])
4168 foundString = [(NSView <WebDocumentIncrementalSearching> *)searchView searchFor:string direction:forward caseSensitive:caseFlag wrap:wrapOnThisPass startInSelection:startInSelection];
4170 foundString = [searchView searchFor:string direction:forward caseSensitive:caseFlag wrap:wrapOnThisPass];
4173 if (frame != startFrame)
4174 [startFrame _clearSelection];
4175 [[self window] makeFirstResponder:searchView];
4183 } while (frame && frame != startFrame);
4185 // If there are multiple frames and wrapFlag is true and we've visited each one without finding a result, we still need to search in the
4186 // first-searched frame up to the selection. However, the API doesn't provide a way to search only up to a particular point. The only
4187 // way to make sure the entire frame is searched is to pass YES for the wrapFlag. When there are no matches, this will search again
4188 // some content that we already searched on the first pass. In the worst case, we could search the entire contents of this frame twice.
4189 // To fix this, we'd need to add a mechanism to specify a range in which to search.
4190 if (wrapFlag && startSearchView) {
4192 if ([startSearchView conformsToProtocol:@protocol(WebDocumentIncrementalSearching)])
4193 foundString = [(NSView <WebDocumentIncrementalSearching> *)startSearchView searchFor:string direction:forward caseSensitive:caseFlag wrap:YES startInSelection:startInSelection];
4195 foundString = [startSearchView searchFor:string direction:forward caseSensitive:caseFlag wrap:YES];
4197 [[self window] makeFirstResponder:startSearchView];
4204 - (void)setHoverFeedbackSuspended:(BOOL)newValue
4206 if (_private->hoverFeedbackSuspended == newValue)
4209 _private->hoverFeedbackSuspended = newValue;
4211 if (_private->usesDocumentViews) {
4212 id <WebDocumentView> documentView = [[[self mainFrame] frameView] documentView];
4213 // FIXME: in a perfect world we'd do this in a general way that worked with any document view,
4214 // such as by calling a protocol method or using respondsToSelector or sending a notification.
4215 // But until there is any need for these more general solutions, we'll just hardwire it to work
4216 // with WebHTMLView.
4217 // Note that _hoverFeedbackSuspendedChanged needs to be called only on the main WebHTMLView, not
4218 // on each subframe separately.
4219 if ([documentView isKindOfClass:[WebHTMLView class]])
4220 [(WebHTMLView *)documentView _hoverFeedbackSuspendedChanged];
4224 [self _updateMouseoverWithFakeEvent];
4227 - (BOOL)isHoverFeedbackSuspended
4229 return _private->hoverFeedbackSuspended;
4232 - (void)setMainFrameDocumentReady:(BOOL)mainFrameDocumentReady
4234 // by setting this to NO, calls to mainFrameDocument are forced to return nil
4235 // setting this to YES lets it return the actual DOMDocument value
4236 // we use this to tell NSTreeController to reset its observers and clear its state
4237 if (_private->mainFrameDocumentReady == mainFrameDocumentReady)
4239 [self _willChangeValueForKey:_WebMainFrameDocumentKey];
4240 _private->mainFrameDocumentReady = mainFrameDocumentReady;
4241 [self _didChangeValueForKey:_WebMainFrameDocumentKey];
4242 // this will cause observers to call mainFrameDocument where this flag will be checked
4245 // This method name is used by Mail on Tiger (but not post-Tiger), so we shouldn't delete it
4246 // until the day comes when we're no longer supporting Mail on Tiger.
4247 - (WebFrame *)_frameForCurrentSelection
4249 return [self _selectedOrMainFrame];
4252 - (void)setTabKeyCyclesThroughElements:(BOOL)cyclesElements
4254 _private->tabKeyCyclesThroughElementsChanged = YES;
4256 _private->page->setTabKeyCyclesThroughElements(cyclesElements);
4259 - (BOOL)tabKeyCyclesThroughElements
4261 return _private->page && _private->page->tabKeyCyclesThroughElements();
4264 - (void)setScriptDebugDelegate:(id)delegate
4266 _private->scriptDebugDelegate = delegate;
4267 [self _cacheScriptDebugDelegateImplementations];
4270 [self _attachScriptDebuggerToAllFrames];
4272 [self _detachScriptDebuggerFromAllFrames];
4275 - (id)scriptDebugDelegate
4277 return _private->scriptDebugDelegate;
4280 - (void)setHistoryDelegate:(id)delegate
4282 _private->historyDelegate = delegate;
4283 [self _cacheHistoryDelegateImplementations];
4286 - (id)historyDelegate
4288 return _private->historyDelegate;
4293 Frame* coreFrame = [self _mainCoreFrame];
4296 return coreFrame->loader()->shouldClose();
4299 static NSAppleEventDescriptor* aeDescFromJSValue(ExecState* exec, JSValue jsValue)
4301 NSAppleEventDescriptor* aeDesc = 0;
4302 if (jsValue.isBoolean())
4303 return [NSAppleEventDescriptor descriptorWithBoolean:jsValue.getBoolean()];
4304 if (jsValue.isString())
4305 return [NSAppleEventDescriptor descriptorWithString:ustringToString(jsValue.getString(exec))];
4306 if (jsValue.isNumber()) {
4307 double value = jsValue.uncheckedGetNumber();
4308 int intValue = value;
4309 if (value == intValue)
4310 return [NSAppleEventDescriptor descriptorWithDescriptorType:typeSInt32 bytes:&intValue length:sizeof(intValue)];
4311 return [NSAppleEventDescriptor descriptorWithDescriptorType:typeIEEE64BitFloatingPoint bytes:&value length:sizeof(value)];
4313 if (jsValue.isObject()) {
4314 JSObject* object = jsValue.getObject();
4315 if (object->inherits(&DateInstance::info)) {
4316 DateInstance* date = static_cast<DateInstance*>(object);
4317 double ms = date->internalNumber();
4319 CFAbsoluteTime utcSeconds = ms / 1000 - kCFAbsoluteTimeIntervalSince1970;
4321 if (noErr == UCConvertCFAbsoluteTimeToLongDateTime(utcSeconds, &ldt))
4322 return [NSAppleEventDescriptor descriptorWithDescriptorType:typeLongDateTime bytes:&ldt length:sizeof(ldt)];
4325 else if (object->inherits(&JSArray::info)) {
4326 DEFINE_STATIC_LOCAL(HashSet<JSObject*>, visitedElems, ());
4327 if (!visitedElems.contains(object)) {
4328 visitedElems.add(object);
4330 JSArray* array = static_cast<JSArray*>(object);
4331 aeDesc = [NSAppleEventDescriptor listDescriptor];
4332 unsigned numItems = array->length();
4333 for (unsigned i = 0; i < numItems; ++i)
4334 [aeDesc insertDescriptor:aeDescFromJSValue(exec, array->get(exec, i)) atIndex:0];
4336 visitedElems.remove(object);
4340 JSValue primitive = object->toPrimitive(exec);
4341 if (exec->hadException()) {
4342 exec->clearException();
4343 return [NSAppleEventDescriptor nullDescriptor];
4345 return aeDescFromJSValue(exec, primitive);
4347 if (jsValue.isUndefined())
4348 return [NSAppleEventDescriptor descriptorWithTypeCode:cMissingValue];
4349 ASSERT(jsValue.isNull());
4350 return [NSAppleEventDescriptor nullDescriptor];
4353 - (NSAppleEventDescriptor *)aeDescByEvaluatingJavaScriptFromString:(NSString *)script
4355 Frame* coreFrame = [self _mainCoreFrame];
4358 if (!coreFrame->document())
4360 JSValue result = coreFrame->script()->executeScript(script, true).jsValue();
4361 if (!result) // FIXME: pass errors
4363 JSLock lock(SilenceAssertionsOnly);
4364 return aeDescFromJSValue(coreFrame->script()->globalObject(mainThreadNormalWorld())->globalExec(), result);
4367 - (BOOL)canMarkAllTextMatches
4369 WebFrame *frame = [self mainFrame];
4371 id <WebDocumentView> view = [[frame frameView] documentView];
4372 if (view && ![view conformsToProtocol:@protocol(WebMultipleTextMatches)])
4375 frame = incrementFrame(frame, YES, NO);
4381 - (NSUInteger)markAllMatchesForText:(NSString *)string caseSensitive:(BOOL)caseFlag highlight:(BOOL)highlight limit:(NSUInteger)limit
4383 if (_private->closed)
4386 return [self countMatchesForText:string caseSensitive:caseFlag highlight:highlight limit:limit markMatches:YES];
4389 - (NSUInteger)countMatchesForText:(NSString *)string caseSensitive:(BOOL)caseFlag highlight:(BOOL)highlight limit:(NSUInteger)limit markMatches:(BOOL)markMatches
4391 if (_private->closed)
4394 WebFrame *frame = [self mainFrame];
4395 unsigned matchCount = 0;
4397 id <WebDocumentView> view = [[frame frameView] documentView];
4398 if ([view conformsToProtocol:@protocol(WebMultipleTextMatches)]) {
4400 [(NSView <WebMultipleTextMatches>*)view setMarkedTextMatchesAreHighlighted:highlight];
4402 ASSERT(limit == 0 || matchCount < limit);
4403 matchCount += [(NSView <WebMultipleTextMatches>*)view countMatchesForText:string caseSensitive:caseFlag limit:limit == 0 ? 0 : limit - matchCount markMatches:markMatches];
4405 // Stop looking if we've reached the limit. A limit of 0 means no limit.
4406 if (limit > 0 && matchCount >= limit)
4410 frame = incrementFrame(frame, YES, NO);
4416 - (void)unmarkAllTextMatches
4418 if (_private->closed)
4421 WebFrame *frame = [self mainFrame];
4423 id <WebDocumentView> view = [[frame frameView] documentView];
4424 if ([view conformsToProtocol:@protocol(WebMultipleTextMatches)])
4425 [(NSView <WebMultipleTextMatches>*)view unmarkAllTextMatches];
4427 frame = incrementFrame(frame, YES, NO);
4431 - (NSArray *)rectsForTextMatches
4433 if (_private->closed)
4434 return [NSArray array];
4436 NSMutableArray *result = [NSMutableArray array];
4437 WebFrame *frame = [self mainFrame];
4439 id <WebDocumentView> view = [[frame frameView] documentView];
4440 if ([view conformsToProtocol:@protocol(WebMultipleTextMatches)]) {
4441 NSView <WebMultipleTextMatches> *documentView = (NSView <WebMultipleTextMatches> *)view;
4442 NSRect documentViewVisibleRect = [documentView visibleRect];
4443 NSArray *originalRects = [documentView rectsForTextMatches];
4444 unsigned rectCount = [originalRects count];
4446 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
4447 for (rectIndex = 0; rectIndex < rectCount; ++rectIndex) {
4448 NSRect r = [[originalRects objectAtIndex:rectIndex] rectValue];
4449 // Clip rect to document view's visible rect so rect is confined to subframe
4450 r = NSIntersectionRect(r, documentViewVisibleRect);
4451 if (NSIsEmptyRect(r))
4454 // Convert rect to our coordinate system
4455 r = [documentView convertRect:r toView:self];
4456 [result addObject:[NSValue valueWithRect:r]];
4457 if (rectIndex % 10 == 0) {
4459 pool = [[NSAutoreleasePool alloc] init];
4465 frame = incrementFrame(frame, YES, NO);
4471 - (void)scrollDOMRangeToVisible:(DOMRange *)range
4473 [[[[range startContainer] ownerDocument] webFrame] _scrollDOMRangeToVisible:range];
4478 return _private->allowsUndo;
4481 - (void)setAllowsUndo:(BOOL)flag
4483 _private->allowsUndo = flag;
4486 - (void)setPageSizeMultiplier:(float)m
4488 [self _setZoomMultiplier:m isTextOnly:NO];
4491 - (float)pageSizeMultiplier
4493 return ![self _realZoomMultiplierIsTextOnly] ? _private->zoomMultiplier : 1.0f;
4496 - (BOOL)canZoomPageIn
4498 return [self _canZoomIn:NO];
4501 - (IBAction)zoomPageIn:(id)sender
4503 return [self _zoomIn:sender isTextOnly:NO];
4506 - (BOOL)canZoomPageOut
4508 return [self _canZoomOut:NO];
4511 - (IBAction)zoomPageOut:(id)sender
4513 return [self _zoomOut:sender isTextOnly:NO];
4516 - (BOOL)canResetPageZoom
4518 return [self _canResetZoom:NO];
4521 - (IBAction)resetPageZoom:(id)sender
4523 return [self _resetZoom:sender isTextOnly:NO];
4526 - (void)setMediaVolume:(float)volume
4529 _private->page->setMediaVolume(volume);
4532 - (float)mediaVolume
4534 if (!_private->page)
4537 return _private->page->mediaVolume();
4540 - (void)addVisitedLinks:(NSArray *)visitedLinks
4542 PageGroup& group = core(self)->group();
4544 NSEnumerator *enumerator = [visitedLinks objectEnumerator];
4545 while (NSString *url = [enumerator nextObject]) {
4546 size_t length = [url length];
4547 const UChar* characters = CFStringGetCharactersPtr(reinterpret_cast<CFStringRef>(url));
4549 group.addVisitedLink(characters, length);
4551 Vector<UChar, 512> buffer(length);
4552 [url getCharacters:buffer.data()];
4553 group.addVisitedLink(buffer.data(), length);
4560 @implementation WebView (WebViewPrintingPrivate)
4562 - (float)_headerHeight
4564 return CallUIDelegateReturningFloat(self, @selector(webViewHeaderHeight:));
4567 - (float)_footerHeight
4569 return CallUIDelegateReturningFloat(self, @selector(webViewFooterHeight:));
4572 - (void)_drawHeaderInRect:(NSRect)rect
4574 #ifdef DEBUG_HEADER_AND_FOOTER
4575 NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
4576 [currentContext saveGraphicsState];
4577 [[NSColor yellowColor] set];
4579 [currentContext restoreGraphicsState];
4582 SEL selector = @selector(webView:drawHeaderInRect:);
4583 if (![_private->UIDelegate respondsToSelector:selector])
4586 NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
4587 [currentContext saveGraphicsState];
4590 CallUIDelegate(self, selector, rect);
4592 [currentContext restoreGraphicsState];
4595 - (void)_drawFooterInRect:(NSRect)rect
4597 #ifdef DEBUG_HEADER_AND_FOOTER
4598 NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
4599 [currentContext saveGraphicsState];
4600 [[NSColor cyanColor] set];
4602 [currentContext restoreGraphicsState];
4605 SEL selector = @selector(webView:drawFooterInRect:);
4606 if (![_private->UIDelegate respondsToSelector:selector])
4609 NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
4610 [currentContext saveGraphicsState];
4613 CallUIDelegate(self, selector, rect);
4615 [currentContext restoreGraphicsState];
4618 - (void)_adjustPrintingMarginsForHeaderAndFooter
4620 NSPrintOperation *op = [NSPrintOperation currentOperation];
4621 NSPrintInfo *info = [op printInfo];
4622 NSMutableDictionary *infoDictionary = [info dictionary];
4624 // We need to modify the top and bottom margins in the NSPrintInfo to account for the space needed by the
4625 // header and footer. Because this method can be called more than once on the same NSPrintInfo (see 5038087),
4626 // we stash away the unmodified top and bottom margins the first time this method is called, and we read from
4627 // those stashed-away values on subsequent calls.
4628 float originalTopMargin;
4629 float originalBottomMargin;
4630 NSNumber *originalTopMarginNumber = [infoDictionary objectForKey:WebKitOriginalTopPrintingMarginKey];
4631 if (!originalTopMarginNumber) {
4632 ASSERT(![infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey]);
4633 originalTopMargin = [info topMargin];
4634 originalBottomMargin = [info bottomMargin];
4635 [infoDictionary setObject:[NSNumber numberWithFloat:originalTopMargin] forKey:WebKitOriginalTopPrintingMarginKey];
4636 [infoDictionary setObject:[NSNumber numberWithFloat:originalBottomMargin] forKey:WebKitOriginalBottomPrintingMarginKey];
4638 ASSERT([originalTopMarginNumber isKindOfClass:[NSNumber class]]);
4639 ASSERT([[infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey] isKindOfClass:[NSNumber class]]);
4640 originalTopMargin = [originalTopMarginNumber floatValue];
4641 originalBottomMargin = [[infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey] floatValue];
4644 float scale = [op _web_pageSetupScaleFactor];
4645 [info setTopMargin:originalTopMargin + [self _headerHeight] * scale];
4646 [info setBottomMargin:originalBottomMargin + [self _footerHeight] * scale];
4649 - (void)_drawHeaderAndFooter
4651 // The header and footer rect height scales with the page, but the width is always
4652 // all the way across the printed page (inset by printing margins).
4653 NSPrintOperation *op = [NSPrintOperation currentOperation];
4654 float scale = [op _web_pageSetupScaleFactor];
4655 NSPrintInfo *printInfo = [op printInfo];
4656 NSSize paperSize = [printInfo paperSize];
4657 float headerFooterLeft = [printInfo leftMargin]/scale;
4658 float headerFooterWidth = (paperSize.width - ([printInfo leftMargin] + [printInfo rightMargin]))/scale;
4659 NSRect footerRect = NSMakeRect(headerFooterLeft, [printInfo bottomMargin]/scale - [self _footerHeight] ,
4660 headerFooterWidth, [self _footerHeight]);
4661 NSRect headerRect = NSMakeRect(headerFooterLeft, (paperSize.height - [printInfo topMargin])/scale,
4662 headerFooterWidth, [self _headerHeight]);
4664 [self _drawHeaderInRect:headerRect];
4665 [self _drawFooterInRect:footerRect];
4669 @implementation WebView (WebDebugBinding)
4671 - (void)addObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context
4673 LOG (Bindings, "addObserver:%p forKeyPath:%@ options:%x context:%p", anObserver, keyPath, options, context);
4674 [super addObserver:anObserver forKeyPath:keyPath options:options context:context];
4677 - (void)removeObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath
4679 LOG (Bindings, "removeObserver:%p forKeyPath:%@", anObserver, keyPath);
4680 [super removeObserver:anObserver forKeyPath:keyPath];
4685 //==========================================================================================
4688 @implementation WebView (WebViewCSS)
4690 - (DOMCSSStyleDeclaration *)computedStyleForElement:(DOMElement *)element pseudoElement:(NSString *)pseudoElement
4692 // FIXME: is this the best level for this conversion?
4693 if (pseudoElement == nil)
4694 pseudoElement = @"";
4696 return [[element ownerDocument] getComputedStyle:element pseudoElement:pseudoElement];
4701 @implementation WebView (WebViewEditing)
4703 - (DOMRange *)editableDOMRangeForPoint:(NSPoint)point
4705 Page* page = core(self);
4708 return kit(page->mainFrame()->editor()->rangeForPoint(IntPoint([self convertPoint:point toView:nil])).get());
4711 - (BOOL)_shouldChangeSelectedDOMRange:(DOMRange *)currentRange toDOMRange:(DOMRange *)proposedRange affinity:(NSSelectionAffinity)selectionAffinity stillSelecting:(BOOL)flag
4713 // FIXME: This quirk is needed due to <rdar://problem/4985321> - We can phase it out once Aperture can adopt the new behavior on their end
4714 if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_APERTURE_QUIRK) && [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.Aperture"])
4716 return [[self _editingDelegateForwarder] webView:self shouldChangeSelectedDOMRange:currentRange toDOMRange:proposedRange affinity:selectionAffinity stillSelecting:flag];
4719 - (BOOL)maintainsInactiveSelection
4724 - (void)setSelectedDOMRange:(DOMRange *)range affinity:(NSSelectionAffinity)selectionAffinity
4726 Frame* coreFrame = core([self _selectedOrMainFrame]);
4731 coreFrame->selection()->clear();
4733 // Derive the frame to use from the range passed in.
4734 // Using _selectedOrMainFrame could give us a different document than
4735 // the one the range uses.
4736 coreFrame = core([range startContainer])->document()->frame();
4740 coreFrame->selection()->setSelectedRange(core(range), core(selectionAffinity), true);
4744 - (DOMRange *)selectedDOMRange
4746 Frame* coreFrame = core([self _selectedOrMainFrame]);
4749 return kit(coreFrame->selection()->toNormalizedRange().get());
4752 - (NSSelectionAffinity)selectionAffinity
4754 Frame* coreFrame = core([self _selectedOrMainFrame]);
4756 return NSSelectionAffinityDownstream;
4757 return kit(coreFrame->selection()->affinity());
4760 - (void)setEditable:(BOOL)flag
4762 if (_private->editable != flag) {
4763 _private->editable = flag;
4764 if (!_private->tabKeyCyclesThroughElementsChanged && _private->page)
4765 _private->page->setTabKeyCyclesThroughElements(!flag);
4766 Frame* mainFrame = [self _mainCoreFrame];
4769 mainFrame->editor()->applyEditingStyleToBodyElement();
4770 // If the WebView is made editable and the selection is empty, set it to something.
4771 if (![self selectedDOMRange])
4772 mainFrame->setSelectionFromNone();
4780 return _private->editable;
4783 - (void)setTypingStyle:(DOMCSSStyleDeclaration *)style
4785 // We don't know enough at thls level to pass in a relevant WebUndoAction; we'd have to
4786 // change the API to allow this.
4787 [[self _selectedOrMainFrame] _setTypingStyle:style withUndoAction:EditActionUnspecified];
4790 - (DOMCSSStyleDeclaration *)typingStyle
4792 return [[self _selectedOrMainFrame] _typingStyle];
4795 - (void)setSmartInsertDeleteEnabled:(BOOL)flag
4797 if (_private->smartInsertDeleteEnabled != flag) {
4798 _private->smartInsertDeleteEnabled = flag;
4799 [[NSUserDefaults standardUserDefaults] setBool:_private->smartInsertDeleteEnabled forKey:WebSmartInsertDeleteEnabled];
4802 [self setSelectTrailingWhitespaceEnabled:false];
4805 - (BOOL)smartInsertDeleteEnabled
4807 return _private->smartInsertDeleteEnabled;
4810 - (void)setContinuousSpellCheckingEnabled:(BOOL)flag
4812 if (continuousSpellCheckingEnabled != flag) {
4813 continuousSpellCheckingEnabled = flag;
4814 [[NSUserDefaults standardUserDefaults] setBool:continuousSpellCheckingEnabled forKey:WebContinuousSpellCheckingEnabled];
4817 if ([self isContinuousSpellCheckingEnabled]) {
4818 [[self class] _preflightSpellChecker];
4820 [[self mainFrame] _unmarkAllMisspellings];
4824 - (BOOL)isContinuousSpellCheckingEnabled
4826 return (continuousSpellCheckingEnabled && [self _continuousCheckingAllowed]);
4829 - (NSInteger)spellCheckerDocumentTag
4831 if (!_private->hasSpellCheckerDocumentTag) {
4832 _private->spellCheckerDocumentTag = [NSSpellChecker uniqueSpellDocumentTag];
4833 _private->hasSpellCheckerDocumentTag = YES;
4835 return _private->spellCheckerDocumentTag;
4838 - (NSUndoManager *)undoManager
4840 if (!_private->allowsUndo)
4843 NSUndoManager *undoManager = [[self _editingDelegateForwarder] undoManagerForWebView:self];
4847 return [super undoManager];
4850 - (void)registerForEditingDelegateNotification:(NSString *)name selector:(SEL)selector
4852 NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
4853 if ([_private->editingDelegate respondsToSelector:selector])
4854 [defaultCenter addObserver:_private->editingDelegate selector:selector name:name object:self];
4857 - (void)setEditingDelegate:(id)delegate
4859 if (_private->editingDelegate == delegate)
4862 NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
4864 // remove notifications from current delegate
4865 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidBeginEditingNotification object:self];
4866 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidChangeNotification object:self];
4867 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidEndEditingNotification object:self];
4868 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidChangeTypingStyleNotification object:self];
4869 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidChangeSelectionNotification object:self];
4871 _private->editingDelegate = delegate;
4872 [_private->editingDelegateForwarder release];
4873 _private->editingDelegateForwarder = nil;
4875 // add notifications for new delegate
4876 [self registerForEditingDelegateNotification:WebViewDidBeginEditingNotification selector:@selector(webViewDidBeginEditing:)];
4877 [self registerForEditingDelegateNotification:WebViewDidChangeNotification selector:@selector(webViewDidChange:)];
4878 [self registerForEditingDelegateNotification:WebViewDidEndEditingNotification selector:@selector(webViewDidEndEditing:)];
4879 [self registerForEditingDelegateNotification:WebViewDidChangeTypingStyleNotification selector:@selector(webViewDidChangeTypingStyle:)];
4880 [self registerForEditingDelegateNotification:WebViewDidChangeSelectionNotification selector:@selector(webViewDidChangeSelection:)];
4883 - (id)editingDelegate
4885 return _private->editingDelegate;
4888 - (DOMCSSStyleDeclaration *)styleDeclarationWithText:(NSString *)text
4890 // FIXME: Should this really be attached to the document with the current selection?
4891 DOMCSSStyleDeclaration *decl = [[[self _selectedOrMainFrame] DOMDocument] createCSSStyleDeclaration];
4892 [decl setCssText:text];
4898 @implementation WebView (WebViewGrammarChecking)
4900 // FIXME: This method should be merged into WebViewEditing when we're not in API freeze
4901 - (BOOL)isGrammarCheckingEnabled
4903 #ifdef BUILDING_ON_TIGER
4906 return grammarCheckingEnabled;
4910 #ifndef BUILDING_ON_TIGER
4911 // FIXME: This method should be merged into WebViewEditing when we're not in API freeze
4912 - (void)setGrammarCheckingEnabled:(BOOL)flag
4914 if (grammarCheckingEnabled == flag)
4917 grammarCheckingEnabled = flag;
4918 [[NSUserDefaults standardUserDefaults] setBool:grammarCheckingEnabled forKey:WebGrammarCheckingEnabled];
4920 #ifndef BUILDING_ON_LEOPARD
4921 [[NSSpellChecker sharedSpellChecker] updatePanels];
4923 NSSpellChecker *spellChecker = [NSSpellChecker sharedSpellChecker];
4924 if ([spellChecker respondsToSelector:@selector(_updateGrammar)])
4925 [spellChecker performSelector:@selector(_updateGrammar)];
4928 // We call _preflightSpellChecker when turning continuous spell checking on, but we don't need to do that here
4929 // because grammar checking only occurs on code paths that already preflight spell checking appropriately.
4931 if (![self isGrammarCheckingEnabled])
4932 [[self mainFrame] _unmarkAllBadGrammar];
4935 // FIXME: This method should be merged into WebIBActions when we're not in API freeze
4936 - (void)toggleGrammarChecking:(id)sender
4938 [self setGrammarCheckingEnabled:![self isGrammarCheckingEnabled]];
4944 @implementation WebView (WebViewTextChecking)
4946 - (BOOL)isAutomaticQuoteSubstitutionEnabled
4948 #if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
4951 return automaticQuoteSubstitutionEnabled;
4955 - (BOOL)isAutomaticLinkDetectionEnabled
4957 #if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
4960 return automaticLinkDetectionEnabled;
4964 - (BOOL)isAutomaticDashSubstitutionEnabled
4966 #if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
4969 return automaticDashSubstitutionEnabled;
4973 - (BOOL)isAutomaticTextReplacementEnabled
4975 #if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
4978 return automaticTextReplacementEnabled;
4982 - (BOOL)isAutomaticSpellingCorrectionEnabled
4984 #if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
4987 return automaticSpellingCorrectionEnabled;
4991 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
4993 - (void)setAutomaticQuoteSubstitutionEnabled:(BOOL)flag
4995 if (automaticQuoteSubstitutionEnabled == flag)
4997 automaticQuoteSubstitutionEnabled = flag;
4998 [[NSUserDefaults standardUserDefaults] setBool:automaticQuoteSubstitutionEnabled forKey:WebAutomaticQuoteSubstitutionEnabled];
4999 [[NSSpellChecker sharedSpellChecker] updatePanels];
5002 - (void)toggleAutomaticQuoteSubstitution:(id)sender
5004 [self setAutomaticQuoteSubstitutionEnabled:![self isAutomaticQuoteSubstitutionEnabled]];
5007 - (void)setAutomaticLinkDetectionEnabled:(BOOL)flag
5009 if (automaticLinkDetectionEnabled == flag)
5011 automaticLinkDetectionEnabled = flag;
5012 [[NSUserDefaults standardUserDefaults] setBool:automaticLinkDetectionEnabled forKey:WebAutomaticLinkDetectionEnabled];
5013 [[NSSpellChecker sharedSpellChecker] updatePanels];
5016 - (void)toggleAutomaticLinkDetection:(id)sender
5018 [self setAutomaticLinkDetectionEnabled:![self isAutomaticLinkDetectionEnabled]];
5021 - (void)setAutomaticDashSubstitutionEnabled:(BOOL)flag
5023 if (automaticDashSubstitutionEnabled == flag)
5025 automaticDashSubstitutionEnabled = flag;
5026 [[NSUserDefaults standardUserDefaults] setBool:automaticDashSubstitutionEnabled forKey:WebAutomaticDashSubstitutionEnabled];
5027 [[NSSpellChecker sharedSpellChecker] updatePanels];
5030 - (void)toggleAutomaticDashSubstitution:(id)sender
5032 [self setAutomaticDashSubstitutionEnabled:![self isAutomaticDashSubstitutionEnabled]];
5035 - (void)setAutomaticTextReplacementEnabled:(BOOL)flag
5037 if (automaticTextReplacementEnabled == flag)
5039 automaticTextReplacementEnabled = flag;
5040 [[NSUserDefaults standardUserDefaults] setBool:automaticTextReplacementEnabled forKey:WebAutomaticTextReplacementEnabled];
5041 [[NSSpellChecker sharedSpellChecker] updatePanels];
5044 - (void)toggleAutomaticTextReplacement:(id)sender
5046 [self setAutomaticTextReplacementEnabled:![self isAutomaticTextReplacementEnabled]];
5049 - (void)setAutomaticSpellingCorrectionEnabled:(BOOL)flag
5051 if (automaticSpellingCorrectionEnabled == flag)
5053 automaticSpellingCorrectionEnabled = flag;
5054 [[NSUserDefaults standardUserDefaults] setBool:automaticSpellingCorrectionEnabled forKey:WebAutomaticSpellingCorrectionEnabled];
5055 [[NSSpellChecker sharedSpellChecker] updatePanels];
5058 - (void)toggleAutomaticSpellingCorrection:(id)sender
5060 [self setAutomaticSpellingCorrectionEnabled:![self isAutomaticSpellingCorrectionEnabled]];
5067 @implementation WebView (WebViewUndoableEditing)
5069 - (void)replaceSelectionWithNode:(DOMNode *)node
5071 [[self _selectedOrMainFrame] _replaceSelectionWithNode:node selectReplacement:YES smartReplace:NO matchStyle:NO];
5074 - (void)replaceSelectionWithText:(NSString *)text
5076 [[self _selectedOrMainFrame] _replaceSelectionWithText:text selectReplacement:YES smartReplace:NO];
5079 - (void)replaceSelectionWithMarkupString:(NSString *)markupString
5081 [[self _selectedOrMainFrame] _replaceSelectionWithMarkupString:markupString baseURLString:nil selectReplacement:YES smartReplace:NO];
5084 - (void)replaceSelectionWithArchive:(WebArchive *)archive
5086 [[[self _selectedOrMainFrame] _dataSource] _replaceSelectionWithArchive:archive selectReplacement:YES];
5089 - (void)deleteSelection
5091 WebFrame *webFrame = [self _selectedOrMainFrame];
5092 Frame* coreFrame = core(webFrame);
5094 coreFrame->editor()->deleteSelectionWithSmartDelete([(WebHTMLView *)[[webFrame frameView] documentView] _canSmartCopyOrDelete]);
5097 - (void)applyStyle:(DOMCSSStyleDeclaration *)style
5099 // We don't know enough at thls level to pass in a relevant WebUndoAction; we'd have to
5100 // change the API to allow this.
5101 WebFrame *webFrame = [self _selectedOrMainFrame];
5102 Frame* coreFrame = core(webFrame);
5104 coreFrame->editor()->applyStyle(core(style));
5109 @implementation WebView (WebViewEditingActions)
5111 - (void)_performResponderOperation:(SEL)selector with:(id)parameter
5113 static BOOL reentered = NO;
5115 [[self nextResponder] tryToPerform:selector with:parameter];
5119 // There are two possibilities here.
5121 // One is that WebView has been called in its role as part of the responder chain.
5122 // In that case, it's fine to call the first responder and end up calling down the
5123 // responder chain again. Later we will return here with reentered = YES and continue
5124 // past the WebView.
5126 // The other is that we are being called directly, in which case we want to pass the
5127 // selector down to the view inside us that can handle it, and continue down the
5128 // responder chain as usual.
5130 // Pass this selector down to the first responder.
5131 NSResponder *responder = [self _responderForResponderOperations];
5133 [responder tryToPerform:selector with:parameter];
5137 #define FORWARD(name) \
5138 - (void)name:(id)sender { [self _performResponderOperation:_cmd with:sender]; }
5140 FOR_EACH_RESPONDER_SELECTOR(FORWARD)
5142 - (void)insertText:(NSString *)text
5144 [self _performResponderOperation:_cmd with:text];
5149 @implementation WebView (WebViewEditingInMail)
5151 - (void)_insertNewlineInQuotedContent
5153 [[self _selectedOrMainFrame] _insertParagraphSeparatorInQuotedContent];
5156 - (void)_replaceSelectionWithNode:(DOMNode *)node matchStyle:(BOOL)matchStyle
5158 [[self _selectedOrMainFrame] _replaceSelectionWithNode:node selectReplacement:YES smartReplace:NO matchStyle:matchStyle];
5161 - (BOOL)_selectionIsCaret
5163 Frame* coreFrame = core([self _selectedOrMainFrame]);
5166 return coreFrame->selection()->isCaret();
5169 - (BOOL)_selectionIsAll
5171 Frame* coreFrame = core([self _selectedOrMainFrame]);
5174 return coreFrame->selection()->isAll(MayLeaveEditableContent);
5179 static WebFrameView *containingFrameView(NSView *view)
5181 while (view && ![view isKindOfClass:[WebFrameView class]])
5182 view = [view superview];
5183 return (WebFrameView *)view;
5186 @implementation WebView (WebFileInternal)
5188 + (void)_setCacheModel:(WebCacheModel)cacheModel
5190 if (s_didSetCacheModel && cacheModel == s_cacheModel)
5193 NSString *nsurlCacheDirectory = (NSString *)WebCFAutorelease(WKCopyFoundationCacheDirectory());
5194 if (!nsurlCacheDirectory)
5195 nsurlCacheDirectory = NSHomeDirectory();
5197 // As a fudge factor, use 1000 instead of 1024, in case the reported byte
5198 // count doesn't align exactly to a megabyte boundary.
5199 uint64_t memSize = WebMemorySize() / 1024 / 1000;
5200 unsigned long long diskFreeSize = WebVolumeFreeSize(nsurlCacheDirectory) / 1024 / 1000;
5201 NSURLCache *nsurlCache = [NSURLCache sharedURLCache];
5203 unsigned cacheTotalCapacity = 0;
5204 unsigned cacheMinDeadCapacity = 0;
5205 unsigned cacheMaxDeadCapacity = 0;
5206 double deadDecodedDataDeletionInterval = 0;
5208 unsigned pageCacheCapacity = 0;
5210 NSUInteger nsurlCacheMemoryCapacity = 0;
5211 NSUInteger nsurlCacheDiskCapacity = 0;
5213 switch (cacheModel) {
5214 case WebCacheModelDocumentViewer: {
5215 // Page cache capacity (in pages)
5216 pageCacheCapacity = 0;
5218 // Object cache capacities (in bytes)
5219 if (memSize >= 2048)
5220 cacheTotalCapacity = 96 * 1024 * 1024;
5221 else if (memSize >= 1536)
5222 cacheTotalCapacity = 64 * 1024 * 1024;
5223 else if (memSize >= 1024)
5224 cacheTotalCapacity = 32 * 1024 * 1024;
5225 else if (memSize >= 512)
5226 cacheTotalCapacity = 16 * 1024 * 1024;
5228 cacheMinDeadCapacity = 0;
5229 cacheMaxDeadCapacity = 0;
5231 // Foundation memory cache capacity (in bytes)
5232 nsurlCacheMemoryCapacity = 0;
5234 // Foundation disk cache capacity (in bytes)
5235 nsurlCacheDiskCapacity = [nsurlCache diskCapacity];
5239 case WebCacheModelDocumentBrowser: {
5240 // Page cache capacity (in pages)
5241 if (memSize >= 1024)
5242 pageCacheCapacity = 3;
5243 else if (memSize >= 512)
5244 pageCacheCapacity = 2;
5245 else if (memSize >= 256)
5246 pageCacheCapacity = 1;
5248 pageCacheCapacity = 0;
5250 // Object cache capacities (in bytes)
5251 if (memSize >= 2048)
5252 cacheTotalCapacity = 96 * 1024 * 1024;
5253 else if (memSize >= 1536)
5254 cacheTotalCapacity = 64 * 1024 * 1024;
5255 else if (memSize >= 1024)
5256 cacheTotalCapacity = 32 * 1024 * 1024;
5257 else if (memSize >= 512)
5258 cacheTotalCapacity = 16 * 1024 * 1024;
5260 cacheMinDeadCapacity = cacheTotalCapacity / 8;
5261 cacheMaxDeadCapacity = cacheTotalCapacity / 4;
5263 // Foundation memory cache capacity (in bytes)
5264 if (memSize >= 2048)
5265 nsurlCacheMemoryCapacity = 4 * 1024 * 1024;
5266 else if (memSize >= 1024)
5267 nsurlCacheMemoryCapacity = 2 * 1024 * 1024;
5268 else if (memSize >= 512)
5269 nsurlCacheMemoryCapacity = 1 * 1024 * 1024;
5271 nsurlCacheMemoryCapacity = 512 * 1024;
5273 // Foundation disk cache capacity (in bytes)
5274 if (diskFreeSize >= 16384)
5275 nsurlCacheDiskCapacity = 50 * 1024 * 1024;
5276 else if (diskFreeSize >= 8192)
5277 nsurlCacheDiskCapacity = 40 * 1024 * 1024;
5278 else if (diskFreeSize >= 4096)
5279 nsurlCacheDiskCapacity = 30 * 1024 * 1024;
5281 nsurlCacheDiskCapacity = 20 * 1024 * 1024;
5285 case WebCacheModelPrimaryWebBrowser: {
5286 // Page cache capacity (in pages)
5287 // (Research indicates that value / page drops substantially after 3 pages.)
5288 if (memSize >= 2048)
5289 pageCacheCapacity = 5;
5290 else if (memSize >= 1024)
5291 pageCacheCapacity = 4;
5292 else if (memSize >= 512)
5293 pageCacheCapacity = 3;
5294 else if (memSize >= 256)
5295 pageCacheCapacity = 2;
5297 pageCacheCapacity = 1;
5299 // Object cache capacities (in bytes)
5300 // (Testing indicates that value / MB depends heavily on content and
5301 // browsing pattern. Even growth above 128MB can have substantial
5302 // value / MB for some content / browsing patterns.)
5303 if (memSize >= 2048)
5304 cacheTotalCapacity = 128 * 1024 * 1024;
5305 else if (memSize >= 1536)
5306 cacheTotalCapacity = 96 * 1024 * 1024;
5307 else if (memSize >= 1024)
5308 cacheTotalCapacity = 64 * 1024 * 1024;
5309 else if (memSize >= 512)
5310 cacheTotalCapacity = 32 * 1024 * 1024;
5312 cacheMinDeadCapacity = cacheTotalCapacity / 4;
5313 cacheMaxDeadCapacity = cacheTotalCapacity / 2;
5315 // This code is here to avoid a PLT regression. We can remove it if we
5316 // can prove that the overall system gain would justify the regression.
5317 cacheMaxDeadCapacity = max(24u, cacheMaxDeadCapacity);
5319 deadDecodedDataDeletionInterval = 60;
5321 // Foundation memory cache capacity (in bytes)
5322 // (These values are small because WebCore does most caching itself.)
5323 if (memSize >= 1024)
5324 nsurlCacheMemoryCapacity = 4 * 1024 * 1024;
5325 else if (memSize >= 512)
5326 nsurlCacheMemoryCapacity = 2 * 1024 * 1024;
5327 else if (memSize >= 256)
5328 nsurlCacheMemoryCapacity = 1 * 1024 * 1024;
5330 nsurlCacheMemoryCapacity = 512 * 1024;
5332 // Foundation disk cache capacity (in bytes)
5333 if (diskFreeSize >= 16384)
5334 nsurlCacheDiskCapacity = 175 * 1024 * 1024;
5335 else if (diskFreeSize >= 8192)
5336 nsurlCacheDiskCapacity = 150 * 1024 * 1024;
5337 else if (diskFreeSize >= 4096)
5338 nsurlCacheDiskCapacity = 125 * 1024 * 1024;
5339 else if (diskFreeSize >= 2048)
5340 nsurlCacheDiskCapacity = 100 * 1024 * 1024;
5341 else if (diskFreeSize >= 1024)
5342 nsurlCacheDiskCapacity = 75 * 1024 * 1024;
5344 nsurlCacheDiskCapacity = 50 * 1024 * 1024;
5349 ASSERT_NOT_REACHED();
5352 #ifdef BUILDING_ON_TIGER
5353 // Don't use a big Foundation disk cache on Tiger because, according to the
5354 // PLT, the Foundation disk cache on Tiger is slower than the network.
5355 nsurlCacheDiskCapacity = [nsurlCache diskCapacity];
5358 // Don't shrink a big disk cache, since that would cause churn.
5359 nsurlCacheDiskCapacity = max(nsurlCacheDiskCapacity, [nsurlCache diskCapacity]);
5361 cache()->setCapacities(cacheMinDeadCapacity, cacheMaxDeadCapacity, cacheTotalCapacity);
5362 cache()->setDeadDecodedDataDeletionInterval(deadDecodedDataDeletionInterval);
5363 pageCache()->setCapacity(pageCacheCapacity);
5364 [nsurlCache setMemoryCapacity:nsurlCacheMemoryCapacity];
5365 [nsurlCache setDiskCapacity:nsurlCacheDiskCapacity];
5367 s_cacheModel = cacheModel;
5368 s_didSetCacheModel = YES;
5371 + (WebCacheModel)_cacheModel
5373 return s_cacheModel;
5376 + (WebCacheModel)_didSetCacheModel
5378 return s_didSetCacheModel;
5381 + (WebCacheModel)_maxCacheModelInAnyInstance
5383 WebCacheModel cacheModel = WebCacheModelDocumentViewer;
5384 NSEnumerator *enumerator = [(NSMutableSet *)allWebViewsSet objectEnumerator];
5385 while (WebPreferences *preferences = [[enumerator nextObject] preferences])
5386 cacheModel = max(cacheModel, [preferences cacheModel]);
5390 + (void)_preferencesChangedNotification:(NSNotification *)notification
5392 WebPreferences *preferences = (WebPreferences *)[notification object];
5393 ASSERT([preferences isKindOfClass:[WebPreferences class]]);
5395 WebCacheModel cacheModel = [preferences cacheModel];
5396 if (![self _didSetCacheModel] || cacheModel > [self _cacheModel])
5397 [self _setCacheModel:cacheModel];
5398 else if (cacheModel < [self _cacheModel])
5399 [self _setCacheModel:max([[WebPreferences standardPreferences] cacheModel], [self _maxCacheModelInAnyInstance])];
5402 + (void)_preferencesRemovedNotification:(NSNotification *)notification
5404 WebPreferences *preferences = (WebPreferences *)[notification object];
5405 ASSERT([preferences isKindOfClass:[WebPreferences class]]);
5407 if ([preferences cacheModel] == [self _cacheModel])
5408 [self _setCacheModel:max([[WebPreferences standardPreferences] cacheModel], [self _maxCacheModelInAnyInstance])];
5411 - (WebFrame *)_focusedFrame
5413 NSResponder *resp = [[self window] firstResponder];
5414 if (resp && [resp isKindOfClass:[NSView class]] && [(NSView *)resp isDescendantOf:[[self mainFrame] frameView]]) {
5415 WebFrameView *frameView = containingFrameView((NSView *)resp);
5416 ASSERT(frameView != nil);
5417 return [frameView webFrame];
5425 WebFrame *mainFrame = [self mainFrame];
5426 return [[mainFrame _dataSource] isLoading]
5427 || [[mainFrame provisionalDataSource] isLoading];
5430 - (WebFrameView *)_frameViewAtWindowPoint:(NSPoint)point
5432 if (_private->closed)
5434 ASSERT(_private->usesDocumentViews);
5435 NSView *view = [self hitTest:[[self superview] convertPoint:point fromView:nil]];
5436 if (![view isDescendantOf:[[self mainFrame] frameView]])
5438 WebFrameView *frameView = containingFrameView(view);
5443 + (void)_preflightSpellCheckerNow:(id)sender
5445 [[NSSpellChecker sharedSpellChecker] _preflightChosenSpellServer];
5448 + (void)_preflightSpellChecker
5450 // As AppKit does, we wish to delay tickling the shared spellchecker into existence on application launch.
5451 if ([NSSpellChecker sharedSpellCheckerExists]) {
5452 [self _preflightSpellCheckerNow:self];
5454 [self performSelector:@selector(_preflightSpellCheckerNow:) withObject:self afterDelay:2.0];
5458 - (BOOL)_continuousCheckingAllowed
5460 static BOOL allowContinuousSpellChecking = YES;
5461 static BOOL readAllowContinuousSpellCheckingDefault = NO;
5462 if (!readAllowContinuousSpellCheckingDefault) {
5463 if ([[NSUserDefaults standardUserDefaults] objectForKey:@"NSAllowContinuousSpellChecking"]) {
5464 allowContinuousSpellChecking = [[NSUserDefaults standardUserDefaults] boolForKey:@"NSAllowContinuousSpellChecking"];
5466 readAllowContinuousSpellCheckingDefault = YES;
5468 return allowContinuousSpellChecking;
5471 - (NSResponder *)_responderForResponderOperations
5473 NSResponder *responder = [[self window] firstResponder];
5474 WebFrameView *mainFrameView = [[self mainFrame] frameView];
5476 // If the current responder is outside of the webview, use our main frameView or its
5477 // document view. We also do this for subviews of self that are siblings of the main
5478 // frameView since clients might insert non-webview-related views there (see 4552713).
5479 if (responder != self && ![mainFrameView _web_firstResponderIsSelfOrDescendantView]) {
5480 responder = [mainFrameView documentView];
5482 responder = mainFrameView;
5487 - (void)_openFrameInNewWindowFromMenu:(NSMenuItem *)sender
5489 ASSERT_ARG(sender, [sender isKindOfClass:[NSMenuItem class]]);
5491 NSDictionary *element = [sender representedObject];
5492 ASSERT([element isKindOfClass:[NSDictionary class]]);
5494 WebDataSource *dataSource = [(WebFrame *)[element objectForKey:WebElementFrameKey] dataSource];
5495 NSURLRequest *request = [[dataSource request] copy];
5498 [self _openNewWindowWithRequest:request];
5502 - (void)_searchWithGoogleFromMenu:(id)sender
5504 id documentView = [[[self selectedFrame] frameView] documentView];
5505 if (![documentView conformsToProtocol:@protocol(WebDocumentText)]) {
5509 NSString *selectedString = [(id <WebDocumentText>)documentView selectedString];
5510 if ([selectedString length] == 0) {
5514 NSPasteboard *pasteboard = [NSPasteboard pasteboardWithUniqueName];
5515 [pasteboard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
5516 NSMutableString *s = [selectedString mutableCopy];
5517 const unichar nonBreakingSpaceCharacter = 0xA0;
5518 NSString *nonBreakingSpaceString = [NSString stringWithCharacters:&nonBreakingSpaceCharacter length:1];
5519 [s replaceOccurrencesOfString:nonBreakingSpaceString withString:@" " options:0 range:NSMakeRange(0, [s length])];
5520 [pasteboard setString:s forType:NSStringPboardType];
5523 // FIXME: seems fragile to use the service by name, but this is what AppKit does
5524 NSPerformService(@"Search With Google", pasteboard);
5527 - (void)_searchWithSpotlightFromMenu:(id)sender
5529 id documentView = [[[self selectedFrame] frameView] documentView];
5530 if (![documentView conformsToProtocol:@protocol(WebDocumentText)])
5533 NSString *selectedString = [(id <WebDocumentText>)documentView selectedString];
5534 if (![selectedString length])
5537 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
5538 [[NSWorkspace sharedWorkspace] showSearchResultsForQueryString:selectedString];
5540 (void)HISearchWindowShow((CFStringRef)selectedString, kNilOptions);
5544 #if USE(ACCELERATED_COMPOSITING)
5545 - (void)_clearLayerSyncLoopObserver
5547 if (!_private->layerSyncRunLoopObserver)
5550 CFRunLoopObserverInvalidate(_private->layerSyncRunLoopObserver);
5551 CFRelease(_private->layerSyncRunLoopObserver);
5552 _private->layerSyncRunLoopObserver = 0;
5556 #if ENABLE(VIDEO) && USE(GSTREAMER)
5557 - (void)_clearGlibLoopObserver
5559 if (!_private->glibRunLoopObserver)
5562 CFRunLoopObserverInvalidate(_private->glibRunLoopObserver);
5563 CFRelease(_private->glibRunLoopObserver);
5564 _private->glibRunLoopObserver = 0;
5569 @implementation WebView (WebViewInternal)
5571 + (BOOL)shouldIncludeInWebKitStatistics
5576 - (BOOL)_becomingFirstResponderFromOutside
5578 return _private->becomingFirstResponderFromOutside;
5581 #if ENABLE(ICONDATABASE)
5582 - (void)_receivedIconChangedNotification:(NSNotification *)notification
5584 // Get the URL for this notification
5585 NSDictionary *userInfo = [notification userInfo];
5586 ASSERT([userInfo isKindOfClass:[NSDictionary class]]);
5587 NSString *urlString = [userInfo objectForKey:WebIconNotificationUserInfoURLKey];
5588 ASSERT([urlString isKindOfClass:[NSString class]]);
5590 // If that URL matches the current main frame, dispatch the delegate call, which will also unregister
5591 // us for this notification
5592 if ([[self mainFrameURL] isEqualTo:urlString])
5593 [self _dispatchDidReceiveIconFromWebFrame:[self mainFrame]];
5596 - (void)_registerForIconNotification:(BOOL)listen
5599 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_receivedIconChangedNotification:) name:WebIconDatabaseDidAddIconNotification object:nil];
5601 [[NSNotificationCenter defaultCenter] removeObserver:self name:WebIconDatabaseDidAddIconNotification object:nil];
5604 - (void)_dispatchDidReceiveIconFromWebFrame:(WebFrame *)webFrame
5606 // FIXME: This willChangeValueForKey call is too late, because the icon has already changed by now.
5607 [self _willChangeValueForKey:_WebMainFrameIconKey];
5609 // Since we definitely have an icon and are about to send out the delegate call for that, this WebView doesn't need to listen for the general
5610 // notification any longer
5611 [self _registerForIconNotification:NO];
5613 WebFrameLoadDelegateImplementationCache* cache = &_private->frameLoadDelegateImplementations;
5614 if (cache->didReceiveIconForFrameFunc) {
5615 Image* image = iconDatabase()->iconForPageURL(core(webFrame)->loader()->url().string(), IntSize(16, 16));
5616 if (NSImage *icon = webGetNSImage(image, NSMakeSize(16, 16)))
5617 CallFrameLoadDelegate(cache->didReceiveIconForFrameFunc, self, @selector(webView:didReceiveIcon:forFrame:), icon, webFrame);
5620 [self _didChangeValueForKey:_WebMainFrameIconKey];
5622 #endif // ENABLE(ICONDATABASE)
5624 - (void)_addObject:(id)object forIdentifier:(unsigned long)identifier
5626 ASSERT(!_private->identifierMap.contains(identifier));
5628 // If the identifier map is initially empty it means we're starting a load
5629 // of something. The semantic is that the web view should be around as long
5630 // as something is loading. Because of that we retain the web view.
5631 if (_private->identifierMap.isEmpty())
5634 _private->identifierMap.set(identifier, object);
5637 - (id)_objectForIdentifier:(unsigned long)identifier
5639 return _private->identifierMap.get(identifier).get();
5642 - (void)_removeObjectForIdentifier:(unsigned long)identifier
5644 ASSERT(_private->identifierMap.contains(identifier));
5645 _private->identifierMap.remove(identifier);
5647 // If the identifier map is now empty it means we're no longer loading anything
5648 // and we should release the web view.
5649 if (_private->identifierMap.isEmpty())
5653 - (void)_retrieveKeyboardUIModeFromPreferences:(NSNotification *)notification
5655 CFPreferencesAppSynchronize(UniversalAccessDomain);
5657 Boolean keyExistsAndHasValidFormat;
5658 int mode = CFPreferencesGetAppIntegerValue(AppleKeyboardUIMode, UniversalAccessDomain, &keyExistsAndHasValidFormat);
5660 // The keyboard access mode is reported by two bits:
5661 // Bit 0 is set if feature is on
5662 // Bit 1 is set if full keyboard access works for any control, not just text boxes and lists
5663 // We require both bits to be on.
5664 // I do not know that we would ever get one bit on and the other off since
5665 // checking the checkbox in system preferences which is marked as "Turn on full keyboard access"
5666 // turns on both bits.
5667 _private->_keyboardUIMode = (mode & 0x2) ? KeyboardAccessFull : KeyboardAccessDefault;
5669 // check for tabbing to links
5670 if ([_private->preferences tabsToLinks])
5671 _private->_keyboardUIMode = (KeyboardUIMode)(_private->_keyboardUIMode | KeyboardAccessTabsToLinks);
5674 - (KeyboardUIMode)_keyboardUIMode
5676 if (!_private->_keyboardUIModeAccessed) {
5677 _private->_keyboardUIModeAccessed = YES;
5679 [self _retrieveKeyboardUIModeFromPreferences:nil];
5681 [[NSDistributedNotificationCenter defaultCenter]
5682 addObserver:self selector:@selector(_retrieveKeyboardUIModeFromPreferences:)
5683 name:KeyboardUIModeDidChangeNotification object:nil];
5685 [[NSNotificationCenter defaultCenter]
5686 addObserver:self selector:@selector(_retrieveKeyboardUIModeFromPreferences:)
5687 name:WebPreferencesChangedNotification object:nil];
5689 return _private->_keyboardUIMode;
5692 - (void)_setInsertionPasteboard:(NSPasteboard *)pasteboard
5694 _private->insertionPasteboard = pasteboard;
5697 - (void)_selectionChanged
5699 if (_private->usesDocumentViews) {
5700 id documentView = [[[self _selectedOrMainFrame] frameView] documentView];
5701 if ([documentView isKindOfClass:[WebHTMLView class]])
5702 [documentView _selectionChanged];
5706 // FIXME (Viewless): We'll need code here.
5709 - (Frame*)_mainCoreFrame
5711 return (_private && _private->page) ? _private->page->mainFrame() : 0;
5714 - (WebFrame *)_selectedOrMainFrame
5716 WebFrame *result = [self selectedFrame];
5718 result = [self mainFrame];
5722 #if USE(ACCELERATED_COMPOSITING)
5724 - (BOOL)_needsOneShotDrawingSynchronization
5726 return _private->needsOneShotDrawingSynchronization;
5729 - (void)_setNeedsOneShotDrawingSynchronization:(BOOL)needsSynchronization
5731 _private->needsOneShotDrawingSynchronization = needsSynchronization;
5734 - (BOOL)_syncCompositingChanges
5736 Frame* frame = [self _mainCoreFrame];
5737 if (frame && frame->view())
5738 return frame->view()->syncCompositingStateRecursive();
5744 The order of events with compositing updates is this:
5746 Start of runloop End of runloop
5748 --|-------------------------------------------------------|--
5751 NSWindow update, | CA commit
5754 layerSyncRunLoopObserverCallBack
5756 To avoid flashing, we have to ensure that compositing changes (rendered via
5757 the CoreAnimation rendering display link) appear on screen at the same time
5758 as content painted into the window via the normal WebCore rendering path.
5760 CoreAnimation will commit any layer changes at the end of the runloop via
5761 its "CA commit" observer. Those changes can then appear onscreen at any time
5762 when the display link fires, which can result in unsynchronized rendering.
5764 To fix this, the GraphicsLayerCA code in WebCore does not change the CA
5765 layer tree during style changes and layout; it stores up all changes and
5766 commits them via syncCompositingState(). There are then two situations in
5767 which we can call syncCompositingState():
5769 1. When painting. FrameView::paintContents() makes a call to syncCompositingState().
5771 2. When style changes/layout have made changes to the layer tree which do not
5772 result in painting. In this case we need a run loop observer to do a
5773 syncCompositingState() at an appropriate time. The observer will keep firing
5774 until the time is right (essentially when there are no more pending layouts).
5778 static void layerSyncRunLoopObserverCallBack(CFRunLoopObserverRef, CFRunLoopActivity, void* info)
5780 WebView *webView = reinterpret_cast<WebView*>(info);
5781 NSWindow *window = [webView window];
5783 // An NSWindow may not display in the next runloop cycle after dirtying due to delayed window display logic,
5784 // in which case this observer can fire first. So if the window is due for a display, don't commit
5785 // layer changes, otherwise they'll show on screen before the view drawing.
5786 bool viewsNeedDisplay;
5788 if (window && [window _wrapsCarbonWindow])
5789 viewsNeedDisplay = HIViewGetNeedsDisplay(HIViewGetRoot(static_cast<WindowRef>([window windowRef])));
5792 viewsNeedDisplay = [window viewsNeedDisplay];
5794 if (viewsNeedDisplay)
5797 if ([webView _syncCompositingChanges]) {
5798 [webView _clearLayerSyncLoopObserver];
5799 // AppKit may have disabled screen updates, thinking an upcoming window flush will re-enable them.
5800 // In case setNeedsDisplayInRect() has prevented the window from needing to be flushed, re-enable screen
5802 if (![window isFlushWindowDisabled])
5803 [window _enableScreenUpdatesIfNeeded];
5805 // Since the WebView does not need display, -viewWillDraw will not be called. Perform pending layout now,
5806 // so that the layers draw with up-to-date layout.
5807 [webView _viewWillDrawInternal];
5811 - (void)_scheduleCompositingLayerSync
5813 if (_private->layerSyncRunLoopObserver)
5816 // Run after AppKit does its window update. If we do any painting, we'll commit
5817 // layer changes from FrameView::paintContents(), otherwise we'll commit via
5818 // _syncCompositingChanges when this observer fires.
5819 const CFIndex runLoopOrder = NSDisplayWindowRunLoopOrdering + 1;
5821 // The WebView always outlives the observer, so no need to retain/release.
5822 CFRunLoopObserverContext context = { 0, self, 0, 0, 0 };
5824 _private->layerSyncRunLoopObserver = CFRunLoopObserverCreate(NULL,
5825 kCFRunLoopBeforeWaiting | kCFRunLoopExit, true /* repeats */,
5826 runLoopOrder, layerSyncRunLoopObserverCallBack, &context);
5828 CFRunLoopAddObserver(CFRunLoopGetCurrent(), _private->layerSyncRunLoopObserver, kCFRunLoopCommonModes);
5835 - (void)_enterFullscreenForNode:(WebCore::Node*)node
5837 ASSERT(node->hasTagName(WebCore::HTMLNames::videoTag));
5838 HTMLMediaElement* videoElement = static_cast<HTMLMediaElement*>(node);
5840 if (_private->fullscreenController) {
5841 if ([_private->fullscreenController mediaElement] == videoElement) {
5842 // The backend may just warn us that the underlaying plaftormMovie()
5843 // has changed. Just force an update.
5844 [_private->fullscreenController setMediaElement:videoElement];
5845 return; // No more to do.
5848 // First exit Fullscreen for the old mediaElement.
5849 [_private->fullscreenController mediaElement]->exitFullscreen();
5850 // This previous call has to trigger _exitFullscreen,
5851 // which has to clear _private->fullscreenController.
5852 ASSERT(!_private->fullscreenController);
5854 if (!_private->fullscreenController) {
5855 _private->fullscreenController = [[WebVideoFullscreenController alloc] init];
5856 [_private->fullscreenController setMediaElement:videoElement];
5857 [_private->fullscreenController enterFullscreen:[[self window] screen]];
5860 [_private->fullscreenController setMediaElement:videoElement];
5863 - (void)_exitFullscreen
5865 if (!_private->fullscreenController)
5867 [_private->fullscreenController exitFullscreen];
5868 [_private->fullscreenController release];
5869 _private->fullscreenController = nil;
5874 #if ENABLE(VIDEO) && USE(GSTREAMER)
5876 static void glibContextIterationCallback(CFRunLoopObserverRef, CFRunLoopActivity, void*)
5878 g_main_context_iteration(0, FALSE);
5881 - (void)_scheduleGlibContextIterations
5883 if (_private->glibRunLoopObserver)
5886 NSRunLoop* myRunLoop = [NSRunLoop currentRunLoop];
5888 // Create a run loop observer and attach it to the run loop.
5889 CFRunLoopObserverContext context = {0, self, 0, 0, 0};
5890 _private->glibRunLoopObserver = CFRunLoopObserverCreate(kCFAllocatorDefault, kCFRunLoopBeforeWaiting, YES, 0, &glibContextIterationCallback, &context);
5892 if (_private->glibRunLoopObserver) {
5893 CFRunLoopRef cfLoop = [myRunLoop getCFRunLoop];
5894 CFRunLoopAddObserver(cfLoop, _private->glibRunLoopObserver, kCFRunLoopDefaultMode);
5903 @implementation WebView (WebViewDeviceOrientation)
5905 - (void)_setDeviceOrientationProvider:(id<WebDeviceOrientationProvider>)deviceOrientationProvider
5908 _private->m_deviceOrientationProvider = deviceOrientationProvider;
5911 - (id<WebDeviceOrientationProvider>)_deviceOrientationProvider
5914 return _private->m_deviceOrientationProvider;
5920 @implementation WebView (WebViewGeolocation)
5922 - (void)_setGeolocationProvider:(id<WebGeolocationProvider>)geolocationProvider
5925 _private->_geolocationProvider = geolocationProvider;
5928 - (id<WebGeolocationProvider>)_geolocationProvider
5931 return _private->_geolocationProvider;
5935 - (void)_geolocationDidChangePosition:(WebGeolocationPosition *)position
5937 #if ENABLE(CLIENT_BASED_GEOLOCATION)
5938 if (_private && _private->page)
5939 _private->page->geolocationController()->positionChanged(core(position));
5943 - (void)_geolocationDidFailWithError:(NSError *)error
5945 #if ENABLE(CLIENT_BASED_GEOLOCATION)
5946 if (_private && _private->page) {
5947 RefPtr<GeolocationError> geolocatioError = GeolocationError::create(GeolocationError::PositionUnavailable, [error localizedDescription]);
5948 _private->page->geolocationController()->errorOccurred(geolocatioError.get());
5955 @implementation WebView (WebViewPrivateStyleInfo)
5957 - (JSValueRef)_computedStyleIncludingVisitedInfo:(JSContextRef)context forElement:(JSValueRef)value
5959 JSLock lock(SilenceAssertionsOnly);
5960 ExecState* exec = toJS(context);
5962 return JSValueMakeUndefined(context);
5963 JSValue jsValue = toJS(exec, value);
5964 if (!jsValue.inherits(&JSElement::s_info))
5965 return JSValueMakeUndefined(context);
5966 JSElement* jsElement = static_cast<JSElement*>(asObject(jsValue));
5967 Element* element = jsElement->impl();
5968 RefPtr<CSSComputedStyleDeclaration> style = computedStyle(element, true);
5969 return toRef(exec, toJS(exec, jsElement->globalObject(), style.get()));
5974 #ifdef BUILDING_ON_LEOPARD
5976 static IMP originalRecursivelyRemoveMailAttributesImp;
5978 static id objectElementDataAttribute(DOMHTMLObjectElement *self, SEL)
5980 return [self getAttribute:@"data"];
5983 static void recursivelyRemoveMailAttributes(DOMNode *self, SEL selector, BOOL a, BOOL b, BOOL c)
5985 // While inside this Mail function, change the behavior of -[DOMHTMLObjectElement data] back to what it used to be
5986 // before we fixed a bug in it (see http://trac.webkit.org/changeset/30044 for that change).
5988 // It's a little bit strange to patch a method defined by WebKit, but it helps keep this workaround self-contained.
5990 Method methodToPatch = class_getInstanceMethod(objc_getRequiredClass("DOMHTMLObjectElement"), @selector(data));
5991 IMP originalDataImp = method_setImplementation(methodToPatch, reinterpret_cast<IMP>(objectElementDataAttribute));
5992 originalRecursivelyRemoveMailAttributesImp(self, selector, a, b, c);
5993 method_setImplementation(methodToPatch, originalDataImp);
5998 static void patchMailRemoveAttributesMethod()
6000 #ifdef BUILDING_ON_LEOPARD
6001 if (!WKAppVersionCheckLessThan(@"com.apple.mail", -1, 4.0))
6003 Method methodToPatch = class_getInstanceMethod(objc_getRequiredClass("DOMNode"), @selector(recursivelyRemoveMailAttributes:convertObjectsToImages:convertEditableElements:));
6006 originalRecursivelyRemoveMailAttributesImp = method_setImplementation(methodToPatch, reinterpret_cast<IMP>(recursivelyRemoveMailAttributes));