2 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
3 * Copyright (C) 2006 David Smith (catfish.man@gmail.com)
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15 * its contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #import "WebViewInternal.h"
31 #import "WebViewData.h"
33 #import "DOMCSSStyleDeclarationInternal.h"
34 #import "DOMNodeInternal.h"
35 #import "DOMRangeInternal.h"
36 #import "WebBackForwardListInternal.h"
37 #import "WebBaseNetscapePluginView.h"
39 #import "WebChromeClient.h"
40 #import "WebContextMenuClient.h"
41 #import "WebDOMOperationsPrivate.h"
42 #import "WebDataSourceInternal.h"
43 #import "WebDatabaseManagerInternal.h"
44 #import "WebDefaultEditingDelegate.h"
45 #import "WebDefaultPolicyDelegate.h"
46 #import "WebDefaultUIDelegate.h"
47 #import "WebDelegateImplementationCaching.h"
48 #import "WebDocument.h"
49 #import "WebDocumentInternal.h"
50 #import "WebDownload.h"
51 #import "WebDownloadInternal.h"
52 #import "WebDragClient.h"
53 #import "WebDynamicScrollBarsViewInternal.h"
54 #import "WebEditingDelegate.h"
55 #import "WebEditorClient.h"
56 #import "WebFormDelegatePrivate.h"
57 #import "WebFrameInternal.h"
58 #import "WebFrameViewInternal.h"
59 #import "WebGeolocationControllerClient.h"
60 #import "WebGeolocationPositionInternal.h"
61 #import "WebHTMLRepresentation.h"
62 #import "WebHTMLViewInternal.h"
63 #import "WebHistoryItemInternal.h"
64 #import "WebIconDatabaseInternal.h"
65 #import "WebInspector.h"
66 #import "WebInspectorClient.h"
67 #import "WebKitErrors.h"
68 #import "WebKitLogging.h"
69 #import "WebKitNSStringExtras.h"
70 #import "WebKitStatisticsPrivate.h"
71 #import "WebKitSystemBits.h"
72 #import "WebKitVersionChecks.h"
73 #import "WebLocalizableStrings.h"
74 #import "WebNSDataExtras.h"
75 #import "WebNSDataExtrasPrivate.h"
76 #import "WebNSDictionaryExtras.h"
77 #import "WebNSEventExtras.h"
78 #import "WebNSObjectExtras.h"
79 #import "WebNSPasteboardExtras.h"
80 #import "WebNSPrintOperationExtras.h"
81 #import "WebNSURLExtras.h"
82 #import "WebNSURLRequestExtras.h"
83 #import "WebNSUserDefaultsExtras.h"
84 #import "WebNSViewExtras.h"
85 #import "WebNodeHighlight.h"
86 #import "WebPDFView.h"
87 #import "WebPanelAuthenticationHandler.h"
88 #import "WebPasteboardHelper.h"
89 #import "WebPlatformStrategies.h"
90 #import "WebPluginDatabase.h"
91 #import "WebPluginHalterClient.h"
92 #import "WebPolicyDelegate.h"
93 #import "WebPreferenceKeysPrivate.h"
94 #import "WebPreferencesPrivate.h"
95 #import "WebScriptDebugDelegate.h"
96 #import "WebScriptWorldInternal.h"
97 #import "WebSystemInterface.h"
98 #import "WebTextCompletionController.h"
99 #import "WebTextIterator.h"
100 #import "WebUIDelegate.h"
101 #import "WebUIDelegatePrivate.h"
102 #import "WebVideoFullscreenController.h"
103 #import <CoreFoundation/CFSet.h>
104 #import <Foundation/NSURLConnection.h>
105 #import <JavaScriptCore/APICast.h>
106 #import <JavaScriptCore/JSValueRef.h>
107 #import <WebCore/AbstractDatabase.h>
108 #import <WebCore/ApplicationCacheStorage.h>
109 #import <WebCore/BackForwardList.h>
110 #import <WebCore/Cache.h>
111 #import <WebCore/ColorMac.h>
112 #import <WebCore/CSSComputedStyleDeclaration.h>
113 #import <WebCore/Cursor.h>
114 #import <WebCore/Document.h>
115 #import <WebCore/DocumentLoader.h>
116 #import <WebCore/DragController.h>
117 #import <WebCore/DragData.h>
118 #import <WebCore/Editor.h>
119 #import <WebCore/EventHandler.h>
120 #import <WebCore/ExceptionHandlers.h>
121 #import <WebCore/FocusController.h>
122 #import <WebCore/Frame.h>
123 #import <WebCore/FrameLoader.h>
124 #import <WebCore/FrameTree.h>
125 #import <WebCore/FrameView.h>
126 #import <WebCore/GCController.h>
127 #import <WebCore/HTMLMediaElement.h>
128 #import <WebCore/HTMLNames.h>
129 #import <WebCore/HistoryItem.h>
130 #import <WebCore/IconDatabase.h>
131 #import <WebCore/JSCSSStyleDeclaration.h>
132 #import <WebCore/JSElement.h>
133 #import <WebCore/Logging.h>
134 #import <WebCore/MIMETypeRegistry.h>
135 #import <WebCore/Page.h>
136 #import <WebCore/PageCache.h>
137 #import <WebCore/PageGroup.h>
138 #import <WebCore/PlatformMouseEvent.h>
139 #import <WebCore/ProgressTracker.h>
140 #import <WebCore/RenderWidget.h>
141 #import <WebCore/ResourceHandle.h>
142 #import <WebCore/RuntimeApplicationChecks.h>
143 #import <WebCore/ScriptController.h>
144 #import <WebCore/ScriptValue.h>
145 #import <WebCore/SecurityOrigin.h>
146 #import <WebCore/SelectionController.h>
147 #import <WebCore/Settings.h>
148 #import <WebCore/TextResourceDecoder.h>
149 #import <WebCore/ThreadCheck.h>
150 #import <WebCore/WebCoreObjCExtras.h>
151 #import <WebCore/WebCoreView.h>
152 #import <WebCore/Widget.h>
153 #import <WebKit/DOM.h>
154 #import <WebKit/DOMExtensions.h>
155 #import <WebKit/DOMPrivate.h>
156 #import <WebKitSystemInterface.h>
157 #import <mach-o/dyld.h>
158 #import <objc/objc-auto.h>
159 #import <objc/objc-runtime.h>
160 #import <runtime/ArrayPrototype.h>
161 #import <runtime/DateInstance.h>
162 #import <runtime/InitializeThreading.h>
163 #import <runtime/JSLock.h>
164 #import <runtime/JSValue.h>
165 #import <wtf/Assertions.h>
166 #import <wtf/HashTraits.h>
167 #import <wtf/RefCountedLeakCounter.h>
168 #import <wtf/RefPtr.h>
169 #import <wtf/StdLibExtras.h>
170 #import <wtf/Threading.h>
172 #if ENABLE(DASHBOARD_SUPPORT)
173 #import <WebKit/WebDashboardRegion.h>
176 #if ENABLE(CLIENT_BASED_GEOLOCATION)
177 #import <WebCore/GeolocationController.h>
178 #import <WebCore/GeolocationError.h>
181 #if ENABLE(VIDEO) && USE(GSTREAMER)
185 @interface NSSpellChecker (WebNSSpellCheckerDetails)
186 - (void)_preflightChosenSpellServer;
189 @interface NSView (WebNSViewDetails)
190 - (NSView *)_hitTest:(NSPoint *)aPoint dragTypes:(NSSet *)types;
191 - (void)_autoscrollForDraggingInfo:(id)dragInfo timeDelta:(NSTimeInterval)repeatDelta;
192 - (BOOL)_shouldAutoscrollForDraggingInfo:(id)dragInfo;
195 @interface NSWindow (WebNSWindowDetails)
196 - (id)_oldFirstResponderBeforeBecoming;
197 - (void)_enableScreenUpdatesIfNeeded;
198 - (BOOL)_wrapsCarbonWindow;
201 using namespace WebCore;
204 #if defined(__ppc__) || defined(__ppc64__)
205 #define PROCESSOR "PPC"
206 #elif defined(__i386__) || defined(__x86_64__)
207 #define PROCESSOR "Intel"
209 #error Unknown architecture
212 #define FOR_EACH_RESPONDER_SELECTOR(macro) \
214 macro(alignJustified) \
217 macro(capitalizeWord) \
218 macro(centerSelectionInVisibleArea) \
219 macro(changeAttributes) \
220 macro(changeBaseWritingDirection) \
221 macro(changeBaseWritingDirectionToLTR) \
222 macro(changeBaseWritingDirectionToRTL) \
224 macro(changeDocumentBackgroundColor) \
226 macro(changeSpelling) \
227 macro(checkSpelling) \
233 macro(deleteBackward) \
234 macro(deleteBackwardByDecomposingPreviousCharacter) \
235 macro(deleteForward) \
236 macro(deleteToBeginningOfLine) \
237 macro(deleteToBeginningOfParagraph) \
238 macro(deleteToEndOfLine) \
239 macro(deleteToEndOfParagraph) \
240 macro(deleteToMark) \
241 macro(deleteWordBackward) \
242 macro(deleteWordForward) \
243 macro(ignoreSpelling) \
245 macro(insertBacktab) \
246 macro(insertLineBreak) \
247 macro(insertNewline) \
248 macro(insertNewlineIgnoringFieldEditor) \
249 macro(insertParagraphSeparator) \
251 macro(insertTabIgnoringFieldEditor) \
252 macro(lowercaseWord) \
253 macro(makeBaseWritingDirectionLeftToRight) \
254 macro(makeBaseWritingDirectionRightToLeft) \
255 macro(makeTextWritingDirectionLeftToRight) \
256 macro(makeTextWritingDirectionNatural) \
257 macro(makeTextWritingDirectionRightToLeft) \
258 macro(moveBackward) \
259 macro(moveBackwardAndModifySelection) \
261 macro(moveDownAndModifySelection) \
263 macro(moveForwardAndModifySelection) \
265 macro(moveLeftAndModifySelection) \
266 macro(moveParagraphBackwardAndModifySelection) \
267 macro(moveParagraphForwardAndModifySelection) \
269 macro(moveRightAndModifySelection) \
270 macro(moveToBeginningOfDocument) \
271 macro(moveToBeginningOfDocumentAndModifySelection) \
272 macro(moveToBeginningOfLine) \
273 macro(moveToBeginningOfLineAndModifySelection) \
274 macro(moveToBeginningOfParagraph) \
275 macro(moveToBeginningOfParagraphAndModifySelection) \
276 macro(moveToBeginningOfSentence) \
277 macro(moveToBeginningOfSentenceAndModifySelection) \
278 macro(moveToEndOfDocument) \
279 macro(moveToEndOfDocumentAndModifySelection) \
280 macro(moveToEndOfLine) \
281 macro(moveToEndOfLineAndModifySelection) \
282 macro(moveToEndOfParagraph) \
283 macro(moveToEndOfParagraphAndModifySelection) \
284 macro(moveToEndOfSentence) \
285 macro(moveToEndOfSentenceAndModifySelection) \
286 macro(moveToLeftEndOfLine) \
287 macro(moveToLeftEndOfLineAndModifySelection) \
288 macro(moveToRightEndOfLine) \
289 macro(moveToRightEndOfLineAndModifySelection) \
291 macro(moveUpAndModifySelection) \
292 macro(moveWordBackward) \
293 macro(moveWordBackwardAndModifySelection) \
294 macro(moveWordForward) \
295 macro(moveWordForwardAndModifySelection) \
296 macro(moveWordLeft) \
297 macro(moveWordLeftAndModifySelection) \
298 macro(moveWordRight) \
299 macro(moveWordRightAndModifySelection) \
301 macro(orderFrontSubstitutionsPanel) \
303 macro(pageDownAndModifySelection) \
305 macro(pageUpAndModifySelection) \
307 macro(pasteAsPlainText) \
308 macro(pasteAsRichText) \
310 macro(performFindPanelAction) \
311 macro(scrollLineDown) \
312 macro(scrollLineUp) \
313 macro(scrollPageDown) \
314 macro(scrollPageUp) \
315 macro(scrollToBeginningOfDocument) \
316 macro(scrollToEndOfDocument) \
319 macro(selectParagraph) \
320 macro(selectSentence) \
321 macro(selectToMark) \
324 macro(showGuessPanel) \
325 macro(startSpeaking) \
326 macro(stopSpeaking) \
329 macro(swapWithMark) \
330 macro(takeFindStringFromSelection) \
331 macro(toggleBaseWritingDirection) \
335 macro(uppercaseWord) \
337 macro(yankAndSelect) \
339 #define WebKitOriginalTopPrintingMarginKey @"WebKitOriginalTopMargin"
340 #define WebKitOriginalBottomPrintingMarginKey @"WebKitOriginalBottomMargin"
342 #define KeyboardUIModeDidChangeNotification @"com.apple.KeyboardUIModeDidChange"
343 #define AppleKeyboardUIMode CFSTR("AppleKeyboardUIMode")
344 #define UniversalAccessDomain CFSTR("com.apple.universalaccess")
346 static BOOL s_didSetCacheModel;
347 static WebCacheModel s_cacheModel = WebCacheModelDocumentViewer;
350 static const char webViewIsOpen[] = "At least one WebView is still open.";
353 @interface NSObject (WebValidateWithoutDelegate)
354 - (BOOL)validateUserInterfaceItemWithoutDelegate:(id <NSValidatedUserInterfaceItem>)item;
357 @interface _WebSafeForwarder : NSObject
359 id target; // Non-retained. Don't retain delegates.
361 BOOL catchExceptions;
363 - (id)initWithTarget:(id)target defaultTarget:(id)defaultTarget catchExceptions:(BOOL)catchExceptions;
366 @interface WebView (WebFileInternal)
368 - (WebFrameView *)_frameViewAtWindowPoint:(NSPoint)point;
369 - (WebFrame *)_focusedFrame;
370 + (void)_preflightSpellChecker;
371 - (BOOL)_continuousCheckingAllowed;
372 - (NSResponder *)_responderForResponderOperations;
373 #if USE(ACCELERATED_COMPOSITING)
374 - (void)_clearLayerSyncLoopObserver;
376 #if ENABLE(VIDEO) && USE(GSTREAMER)
377 - (void)_clearGlibLoopObserver;
381 static void patchMailRemoveAttributesMethod();
383 NSString *WebElementDOMNodeKey = @"WebElementDOMNode";
384 NSString *WebElementFrameKey = @"WebElementFrame";
385 NSString *WebElementImageKey = @"WebElementImage";
386 NSString *WebElementImageAltStringKey = @"WebElementImageAltString";
387 NSString *WebElementImageRectKey = @"WebElementImageRect";
388 NSString *WebElementImageURLKey = @"WebElementImageURL";
389 NSString *WebElementIsSelectedKey = @"WebElementIsSelected";
390 NSString *WebElementLinkLabelKey = @"WebElementLinkLabel";
391 NSString *WebElementLinkTargetFrameKey = @"WebElementTargetFrame";
392 NSString *WebElementLinkTitleKey = @"WebElementLinkTitle";
393 NSString *WebElementLinkURLKey = @"WebElementLinkURL";
394 NSString *WebElementSpellingToolTipKey = @"WebElementSpellingToolTip";
395 NSString *WebElementTitleKey = @"WebElementTitle";
396 NSString *WebElementLinkIsLiveKey = @"WebElementLinkIsLive";
397 NSString *WebElementIsInScrollBarKey = @"WebElementIsInScrollBar";
398 NSString *WebElementIsContentEditableKey = @"WebElementIsContentEditableKey";
400 NSString *WebViewProgressStartedNotification = @"WebProgressStartedNotification";
401 NSString *WebViewProgressEstimateChangedNotification = @"WebProgressEstimateChangedNotification";
402 NSString *WebViewProgressFinishedNotification = @"WebProgressFinishedNotification";
404 NSString * const WebViewDidBeginEditingNotification = @"WebViewDidBeginEditingNotification";
405 NSString * const WebViewDidChangeNotification = @"WebViewDidChangeNotification";
406 NSString * const WebViewDidEndEditingNotification = @"WebViewDidEndEditingNotification";
407 NSString * const WebViewDidChangeTypingStyleNotification = @"WebViewDidChangeTypingStyleNotification";
408 NSString * const WebViewDidChangeSelectionNotification = @"WebViewDidChangeSelectionNotification";
410 enum { WebViewVersion = 4 };
412 #define timedLayoutSize 4096
414 static NSMutableSet *schemesWithRepresentationsSet;
416 NSString *_WebCanGoBackKey = @"canGoBack";
417 NSString *_WebCanGoForwardKey = @"canGoForward";
418 NSString *_WebEstimatedProgressKey = @"estimatedProgress";
419 NSString *_WebIsLoadingKey = @"isLoading";
420 NSString *_WebMainFrameIconKey = @"mainFrameIcon";
421 NSString *_WebMainFrameTitleKey = @"mainFrameTitle";
422 NSString *_WebMainFrameURLKey = @"mainFrameURL";
423 NSString *_WebMainFrameDocumentKey = @"mainFrameDocument";
425 NSString *_WebViewDidStartAcceleratedCompositingNotification = @"_WebViewDidStartAcceleratedCompositing";
427 @interface WebProgressItem : NSObject
430 long long bytesReceived;
431 long long estimatedLength;
435 @implementation WebProgressItem
438 static BOOL continuousSpellCheckingEnabled;
439 #ifndef BUILDING_ON_TIGER
440 static BOOL grammarCheckingEnabled;
442 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
443 static BOOL automaticQuoteSubstitutionEnabled;
444 static BOOL automaticLinkDetectionEnabled;
445 static BOOL automaticDashSubstitutionEnabled;
446 static BOOL automaticTextReplacementEnabled;
447 static BOOL automaticSpellingCorrectionEnabled;
450 @implementation WebView (AllWebViews)
452 static CFSetCallBacks NonRetainingSetCallbacks = {
461 static CFMutableSetRef allWebViewsSet;
463 + (void)_makeAllWebViewsPerformSelector:(SEL)selector
468 [(NSMutableSet *)allWebViewsSet makeObjectsPerformSelector:selector];
471 - (void)_removeFromAllWebViewsSet
474 CFSetRemoveValue(allWebViewsSet, self);
477 - (void)_addToAllWebViewsSet
480 allWebViewsSet = CFSetCreateMutable(NULL, 0, &NonRetainingSetCallbacks);
482 CFSetSetValue(allWebViewsSet, self);
487 @implementation WebView (WebPrivate)
489 static inline int callGestalt(OSType selector)
492 Gestalt(selector, &value);
496 // Uses underscores instead of dots because if "4." ever appears in a user agent string, old DHTML libraries treat it as Netscape 4.
497 static NSString *createMacOSXVersionString()
499 // Can't use -[NSProcessInfo operatingSystemVersionString] because it has too much stuff we don't want.
500 int major = callGestalt(gestaltSystemVersionMajor);
503 int minor = callGestalt(gestaltSystemVersionMinor);
504 int bugFix = callGestalt(gestaltSystemVersionBugFix);
506 return [[NSString alloc] initWithFormat:@"%d_%d_%d", major, minor, bugFix];
508 return [[NSString alloc] initWithFormat:@"%d_%d", major, minor];
509 return [[NSString alloc] initWithFormat:@"%d", major];
512 static NSString *createUserVisibleWebKitVersionString()
514 // If the version is 4 digits long or longer, then the first digit represents
515 // the version of the OS. Our user agent string should not include this first digit,
516 // so strip it off and report the rest as the version. <rdar://problem/4997547>
517 NSString *fullVersion = [[NSBundle bundleForClass:[WebView class]] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey];
518 NSRange nonDigitRange = [fullVersion rangeOfCharacterFromSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]];
519 if (nonDigitRange.location == NSNotFound && [fullVersion length] >= 4)
520 return [[fullVersion substringFromIndex:1] copy];
521 if (nonDigitRange.location != NSNotFound && nonDigitRange.location >= 4)
522 return [[fullVersion substringFromIndex:1] copy];
523 return [fullVersion copy];
526 + (NSString *)_standardUserAgentWithApplicationName:(NSString *)applicationName
528 // Note: Do *not* move the initialization of osVersion nor webKitVersion into the declaration.
529 // Garbage collection won't correctly mark the global variable in that case <rdar://problem/5733674>.
530 static NSString *osVersion;
531 static NSString *webKitVersion;
533 osVersion = createMacOSXVersionString();
535 webKitVersion = createUserVisibleWebKitVersionString();
536 NSString *language = [NSUserDefaults _webkit_preferredLanguageCode];
537 if ([applicationName length])
538 return [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; U; " PROCESSOR " Mac OS X %@; %@) AppleWebKit/%@ (KHTML, like Gecko) %@", osVersion, language, webKitVersion, applicationName];
539 return [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; U; " PROCESSOR " Mac OS X %@; %@) AppleWebKit/%@ (KHTML, like Gecko)", osVersion, language, webKitVersion];
542 + (void)_reportException:(JSValueRef)exception inContext:(JSContextRef)context
544 if (!exception || !context)
547 JSLock lock(SilenceAssertionsOnly);
548 JSC::ExecState* execState = toJS(context);
550 // Make sure the context has a DOMWindow global object, otherwise this context didn't originate from a WebView.
551 if (!toJSDOMWindow(execState->lexicalGlobalObject()))
554 reportException(execState, toJS(execState, exception));
557 static void WebKitInitializeApplicationCachePathIfNecessary()
559 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
560 static BOOL initialized = NO;
564 NSString *appName = [[NSBundle mainBundle] bundleIdentifier];
566 appName = [[NSProcessInfo processInfo] processName];
570 NSString* cacheDir = [NSString _webkit_localCacheDirectoryWithBundleIdentifier:appName];
572 cacheStorage().setCacheDirectory(cacheDir);
577 static bool runningLeopardMail()
579 #ifdef BUILDING_ON_LEOPARD
580 return applicationIsAppleMail();
585 static bool runningTigerMail()
587 #ifdef BUILDING_ON_TIGER
588 return applicationIsAppleMail();
593 static bool coreVideoHas7228836Fix()
595 #ifdef BUILDING_ON_LEOPARD
596 NSBundle* coreVideoFrameworkBundle = [NSBundle bundleWithPath:@"/System/Library/Frameworks/CoreVideo.framework"];
597 double version = [[coreVideoFrameworkBundle objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey] doubleValue];
598 return (version >= 48);
603 static bool shouldEnableLoadDeferring()
605 return !applicationIsAdobeInstaller();
608 - (void)_dispatchPendingLoadRequests
610 cache()->loader()->servePendingRequests();
613 - (void)_registerDraggedTypes
615 NSArray *editableTypes = [WebHTMLView _insertablePasteboardTypes];
616 NSArray *URLTypes = [NSPasteboard _web_dragTypesForURL];
617 NSMutableSet *types = [[NSMutableSet alloc] initWithArray:editableTypes];
618 [types addObjectsFromArray:URLTypes];
619 [self registerForDraggedTypes:[types allObjects]];
623 - (BOOL)_usesDocumentViews
625 return _private->usesDocumentViews;
628 - (void)_commonInitializationWithFrameName:(NSString *)frameName groupName:(NSString *)groupName usesDocumentViews:(BOOL)usesDocumentViews
630 WebCoreThreadViolationCheckRoundTwo();
633 WTF::RefCountedLeakCounter::suppressMessages(webViewIsOpen);
636 WebPreferences *standardPreferences = [WebPreferences standardPreferences];
637 [standardPreferences willAddToWebView];
639 _private->preferences = [standardPreferences retain];
640 _private->catchesDelegateExceptions = YES;
641 _private->mainFrameDocumentReady = NO;
642 _private->drawsBackground = YES;
643 _private->backgroundColor = [[NSColor colorWithDeviceWhite:1 alpha:1] retain];
644 _private->usesDocumentViews = usesDocumentViews;
645 _private->includesFlattenedCompositingLayersWhenDrawingToBitmap = YES;
647 WebFrameView *frameView = nil;
648 if (_private->usesDocumentViews) {
649 NSRect f = [self frame];
650 frameView = [[WebFrameView alloc] initWithFrame: NSMakeRect(0,0,f.size.width,f.size.height)];
651 [frameView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
652 [self addSubview:frameView];
656 static bool didOneTimeInitialization = false;
657 if (!didOneTimeInitialization) {
658 WebKitInitializeLoggingChannelsIfNecessary();
659 WebCore::InitializeLoggingChannelsIfNecessary();
660 [WebHistoryItem initWindowWatcherIfNecessary];
662 WebKitInitializeDatabasesIfNecessary();
664 WebKitInitializeApplicationCachePathIfNecessary();
665 patchMailRemoveAttributesMethod();
667 // Initialize our platform strategies.
668 WebPlatformStrategies::initialize();
670 didOneTimeInitialization = true;
673 #if ENABLE(CLIENT_BASED_GEOLOCATION)
674 WebGeolocationControllerClient* geolocationControllerClient = new WebGeolocationControllerClient(self);
676 WebGeolocationControllerClient* geolocationControllerClient = 0;
678 DeviceOrientationClient* deviceOrientationClient = 0;
679 _private->page = new Page(new WebChromeClient(self), new WebContextMenuClient(self), new WebEditorClient(self), new WebDragClient(self), new WebInspectorClient(self), new WebPluginHalterClient(self), geolocationControllerClient, deviceOrientationClient);
681 _private->page->setCanStartMedia([self window]);
682 _private->page->settings()->setLocalStorageDatabasePath([[self preferences] _localStorageDatabasePath]);
684 [WebFrame _createMainFrameWithPage:_private->page frameName:frameName frameView:frameView];
686 #ifndef BUILDING_ON_TIGER
687 NSRunLoop *runLoop = [NSRunLoop mainRunLoop];
689 NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
692 if (WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_LOADING_DURING_COMMON_RUNLOOP_MODES))
693 [self scheduleInRunLoop:runLoop forMode:(NSString *)kCFRunLoopCommonModes];
695 [self scheduleInRunLoop:runLoop forMode:NSDefaultRunLoopMode];
697 [self _addToAllWebViewsSet];
698 [self setGroupName:groupName];
700 // If there's already a next key view (e.g., from a nib), wire it up to our
701 // contained frame view. In any case, wire our next key view up to the our
702 // contained frame view. This works together with our becomeFirstResponder
703 // and setNextKeyView overrides.
704 NSView *nextKeyView = [self nextKeyView];
705 if (nextKeyView && nextKeyView != frameView)
706 [frameView setNextKeyView:nextKeyView];
707 [super setNextKeyView:frameView];
709 if ([[self class] shouldIncludeInWebKitStatistics])
712 [self _registerDraggedTypes];
714 WebPreferences *prefs = [self preferences];
715 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:)
716 name:WebPreferencesChangedNotification object:prefs];
718 // Post a notification so the WebCore settings update.
719 [[self preferences] _postPreferencesChangesNotification];
721 if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_LOCAL_RESOURCE_SECURITY_RESTRICTION)) {
722 // Originally, we allowed all local loads.
723 SecurityOrigin::setLocalLoadPolicy(SecurityOrigin::AllowLocalLoadsForAll);
724 } else if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_MORE_STRICT_LOCAL_RESOURCE_SECURITY_RESTRICTION)) {
725 // Later, we allowed local loads for local URLs and documents loaded
726 // with substitute data.
727 SecurityOrigin::setLocalLoadPolicy(SecurityOrigin::AllowLocalLoadsForLocalAndSubstituteData);
730 if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_CONTENT_SNIFFING_FOR_FILE_URLS))
731 ResourceHandle::forceContentSniffing();
733 #if ENABLE(VIDEO) && USE(GSTREAMER)
734 [self _scheduleGlibContextIterations];
739 - (id)_initWithFrame:(NSRect)f frameName:(NSString *)frameName groupName:(NSString *)groupName usesDocumentViews:(BOOL)usesDocumentViews
741 self = [super initWithFrame:f];
745 #ifdef ENABLE_WEBKIT_UNSET_DYLD_FRAMEWORK_PATH
746 // DYLD_FRAMEWORK_PATH is used so Safari will load the development version of WebKit, which
747 // may not work with other WebKit applications. Unsetting DYLD_FRAMEWORK_PATH removes the
748 // need for Safari to unset it to prevent it from being passed to applications it launches.
749 // Unsetting it when a WebView is first created is as good a place as any.
750 // See <http://bugs.webkit.org/show_bug.cgi?id=4286> for more details.
751 if (getenv("WEBKIT_UNSET_DYLD_FRAMEWORK_PATH")) {
752 unsetenv("DYLD_FRAMEWORK_PATH");
753 unsetenv("WEBKIT_UNSET_DYLD_FRAMEWORK_PATH");
757 _private = [[WebViewPrivate alloc] init];
758 [self _commonInitializationWithFrameName:frameName groupName:groupName usesDocumentViews:usesDocumentViews];
759 [self setMaintainsBackForwardList: YES];
763 - (BOOL)_mustDrawUnionedRect:(NSRect)rect singleRects:(const NSRect *)rects count:(NSInteger)count
765 // If count == 0 here, use the rect passed in for drawing. This is a workaround for:
766 // <rdar://problem/3908282> REGRESSION (Mail): No drag image dragging selected text in Blot and Mail
767 // The reason for the workaround is that this method is called explicitly from the code
768 // to generate a drag image, and at that time, getRectsBeingDrawn:count: will return a zero count.
769 const int cRectThreshold = 10;
770 const float cWastedSpaceThreshold = 0.75f;
771 BOOL useUnionedRect = (count <= 1) || (count > cRectThreshold);
772 if (!useUnionedRect) {
773 // Attempt to guess whether or not we should use the unioned rect or the individual rects.
774 // We do this by computing the percentage of "wasted space" in the union. If that wasted space
775 // is too large, then we will do individual rect painting instead.
776 float unionPixels = (rect.size.width * rect.size.height);
777 float singlePixels = 0;
778 for (int i = 0; i < count; ++i)
779 singlePixels += rects[i].size.width * rects[i].size.height;
780 float wastedSpace = 1 - (singlePixels / unionPixels);
781 if (wastedSpace <= cWastedSpaceThreshold)
782 useUnionedRect = YES;
784 return useUnionedRect;
787 - (void)drawSingleRect:(NSRect)rect
789 ASSERT(!_private->usesDocumentViews);
791 [NSGraphicsContext saveGraphicsState];
795 [[self mainFrame] _drawRect:rect contentsOnly:NO];
797 [[self _UIDelegateForwarder] webView:self didDrawRect:rect];
799 if (WebNodeHighlight *currentHighlight = [self currentNodeHighlight])
800 [currentHighlight setNeedsUpdateInTargetViewRect:rect];
802 [NSGraphicsContext restoreGraphicsState];
803 } @catch (NSException *localException) {
804 [NSGraphicsContext restoreGraphicsState];
805 LOG_ERROR("Exception caught while drawing: %@", localException);
806 [localException raise];
812 return _private && !_private->usesDocumentViews;
815 - (void)setFrameSize:(NSSize)size
817 if (!_private->usesDocumentViews && !NSEqualSizes(_private->lastLayoutSize, size)) {
818 Frame* frame = [self _mainCoreFrame];
819 // FIXME: Viewless WebKit is broken with Safari banners (e.g., the Find banner). We'll have to figure out a way for
820 // Safari to communicate that this space is being consumed. For WebKit with document views, there's no
821 // need to do an explicit resize, since WebFrameViews have auto resizing turned on and will handle changing
822 // their bounds automatically. See <rdar://problem/6835573> for details.
823 frame->view()->resize(IntSize(size));
824 frame->view()->setNeedsLayout();
825 [self setNeedsDisplay:YES];
826 _private->lastLayoutSize = size;
829 [super setFrameSize:size];
832 #if USE(ACCELERATED_COMPOSITING) || !defined(BUILDING_ON_TIGER)
834 - (void)_viewWillDrawInternal
836 Frame* frame = [self _mainCoreFrame];
837 if (frame && frame->view())
838 frame->view()->layoutIfNeededRecursive();
843 #ifndef BUILDING_ON_TIGER
847 if (!_private->usesDocumentViews)
848 [self _viewWillDrawInternal];
849 [super viewWillDraw];
855 - (void)drawRect:(NSRect)rect
857 if (_private->usesDocumentViews)
858 return [super drawRect:rect];
860 ASSERT_MAIN_THREAD();
864 [self getRectsBeingDrawn:&rects count:&count];
867 if ([self _mustDrawUnionedRect:rect singleRects:rects count:count])
868 [self drawSingleRect:rect];
870 for (int i = 0; i < count; ++i)
871 [self drawSingleRect:rects[i]];
874 + (NSArray *)_supportedMIMETypes
876 // Load the plug-in DB allowing plug-ins to install types.
877 [WebPluginDatabase sharedDatabase];
878 return [[WebFrameView _viewTypesAllowImageTypeOmission:NO] allKeys];
881 + (NSArray *)_supportedFileExtensions
883 NSMutableSet *extensions = [[NSMutableSet alloc] init];
884 NSArray *MIMETypes = [self _supportedMIMETypes];
885 NSEnumerator *enumerator = [MIMETypes objectEnumerator];
887 while ((MIMEType = [enumerator nextObject]) != nil) {
888 NSArray *extensionsForType = WKGetExtensionsForMIMEType(MIMEType);
889 if (extensionsForType) {
890 [extensions addObjectsFromArray:extensionsForType];
893 NSArray *uniqueExtensions = [extensions allObjects];
894 [extensions release];
895 return uniqueExtensions;
898 static NSMutableSet *knownPluginMIMETypes()
900 static NSMutableSet *mimeTypes = [[NSMutableSet alloc] init];
905 + (void)_registerPluginMIMEType:(NSString *)MIMEType
907 [WebView registerViewClass:[WebHTMLView class] representationClass:[WebHTMLRepresentation class] forMIMEType:MIMEType];
908 [knownPluginMIMETypes() addObject:MIMEType];
911 + (void)_unregisterPluginMIMEType:(NSString *)MIMEType
913 [self _unregisterViewClassAndRepresentationClassForMIMEType:MIMEType];
914 [knownPluginMIMETypes() removeObject:MIMEType];
917 + (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType allowingPlugins:(BOOL)allowPlugins
919 MIMEType = [MIMEType lowercaseString];
920 Class viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:YES] _webkit_objectForMIMEType:MIMEType];
921 Class repClass = [[WebDataSource _repTypesAllowImageTypeOmission:YES] _webkit_objectForMIMEType:MIMEType];
923 if (!viewClass || !repClass || [[WebPDFView supportedMIMETypes] containsObject:MIMEType]) {
924 // Our optimization to avoid loading the plug-in DB and image types for the HTML case failed.
927 // Load the plug-in DB allowing plug-ins to install types.
928 [WebPluginDatabase sharedDatabase];
931 // Load the image types and get the view class and rep class. This should be the fullest picture of all handled types.
932 viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:NO] _webkit_objectForMIMEType:MIMEType];
933 repClass = [[WebDataSource _repTypesAllowImageTypeOmission:NO] _webkit_objectForMIMEType:MIMEType];
936 if (viewClass && repClass) {
937 if (viewClass == [WebHTMLView class] && repClass == [WebHTMLRepresentation class]) {
938 // Special-case WebHTMLView for text types that shouldn't be shown.
939 if ([[WebHTMLView unsupportedTextMIMETypes] containsObject:MIMEType])
942 // If the MIME type is a known plug-in we might not want to load it.
943 if (!allowPlugins && [knownPluginMIMETypes() containsObject:MIMEType]) {
944 BOOL isSupportedByWebKit = [[WebHTMLView supportedNonImageMIMETypes] containsObject:MIMEType] ||
945 [[WebHTMLView supportedMIMETypes] containsObject:MIMEType];
947 // If this is a known plug-in MIME type and WebKit can't show it natively, we don't want to show it.
948 if (!isSupportedByWebKit)
962 - (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType
964 if ([[self class] _viewClass:vClass andRepresentationClass:rClass forMIMEType:MIMEType allowingPlugins:[_private->preferences arePlugInsEnabled]])
967 if (_private->pluginDatabase) {
968 WebBasePluginPackage *pluginPackage = [_private->pluginDatabase pluginForMIMEType:MIMEType];
971 *vClass = [WebHTMLView class];
973 *rClass = [WebHTMLRepresentation class];
981 + (void)_setAlwaysUseATSU:(BOOL)f
983 [self _setAlwaysUsesComplexTextCodePath:f];
986 + (void)_setAlwaysUsesComplexTextCodePath:(BOOL)f
988 Font::setCodePath(f ? Font::Complex : Font::Auto);
991 + (BOOL)canCloseAllWebViews
993 return DOMWindow::dispatchAllPendingBeforeUnloadEvents();
996 + (void)closeAllWebViews
998 DOMWindow::dispatchAllPendingUnloadEvents();
1000 // This will close the WebViews in a random order. Change this if close order is important.
1001 // Make a new set to avoid mutating the set we are enumerating.
1002 NSSet *webViewsToClose = [NSSet setWithSet:(NSSet *)allWebViewsSet];
1003 NSEnumerator *enumerator = [webViewsToClose objectEnumerator];
1004 while (WebView *webView = [enumerator nextObject])
1008 + (BOOL)canShowFile:(NSString *)path
1010 return [[self class] canShowMIMEType:[WebView _MIMETypeForFile:path]];
1013 + (NSString *)suggestedFileExtensionForMIMEType:(NSString *)type
1015 return WKGetPreferredExtensionForMIMEType(type);
1020 return !_private || _private->closed;
1023 - (void)_closePluginDatabases
1025 pluginDatabaseClientCount--;
1027 // Close both sets of plug-in databases because plug-ins need an opportunity to clean up files, etc.
1029 // Unload the WebView local plug-in database.
1030 if (_private->pluginDatabase) {
1031 [_private->pluginDatabase destroyAllPluginInstanceViews];
1032 [_private->pluginDatabase close];
1033 [_private->pluginDatabase release];
1034 _private->pluginDatabase = nil;
1037 // Keep the global plug-in database active until the app terminates to avoid having to reload plug-in bundles.
1038 if (!pluginDatabaseClientCount && applicationIsTerminating)
1039 [WebPluginDatabase closeSharedDatabase];
1042 - (void)_closeWithFastTeardown
1045 WTF::RefCountedLeakCounter::suppressMessages("At least one WebView was closed with fast teardown.");
1048 [[NSDistributedNotificationCenter defaultCenter] removeObserver:self];
1049 [[NSNotificationCenter defaultCenter] removeObserver:self];
1051 [self _closePluginDatabases];
1054 static bool fastDocumentTeardownEnabled()
1057 static bool enabled = ![[NSUserDefaults standardUserDefaults] boolForKey:WebKitEnableFullDocumentTeardownPreferenceKey];
1059 static bool initialized = false;
1060 static bool enabled = false;
1062 // This allows debug builds to default to not have fast teardown, so leak checking still works.
1063 // But still allow the WebKitEnableFullDocumentTeardown default to override it if present.
1064 NSNumber *setting = [[NSUserDefaults standardUserDefaults] objectForKey:WebKitEnableFullDocumentTeardownPreferenceKey];
1066 enabled = ![setting boolValue];
1073 // _close is here only for backward compatibility; clients and subclasses should use
1074 // public method -close instead.
1077 if (!_private || _private->closed)
1080 _private->closed = YES;
1081 [self _removeFromAllWebViewsSet];
1083 [self _closingEventHandling];
1086 WTF::RefCountedLeakCounter::cancelMessageSuppression(webViewIsOpen);
1089 // To quit the apps fast we skip document teardown, except plugins
1090 // need to be destroyed and unloaded.
1091 if (applicationIsTerminating && fastDocumentTeardownEnabled()) {
1092 [self _closeWithFastTeardown];
1097 [self _exitFullscreen];
1100 if (Frame* mainFrame = [self _mainCoreFrame])
1101 mainFrame->loader()->detachFromParent();
1103 [self setHostWindow:nil];
1105 [self setDownloadDelegate:nil];
1106 [self setEditingDelegate:nil];
1107 [self setFrameLoadDelegate:nil];
1108 [self setPolicyDelegate:nil];
1109 [self setResourceLoadDelegate:nil];
1110 [self setScriptDebugDelegate:nil];
1111 [self setUIDelegate:nil];
1113 [_private->inspector webViewClosed];
1115 // To avoid leaks, call removeDragCaret in case it wasn't called after moveDragCaretToPoint.
1116 [self removeDragCaret];
1118 // Deleteing the WebCore::Page will clear the page cache so we call destroy on
1119 // all the plug-ins in the page cache to break any retain cycles.
1120 // See comment in HistoryItem::releaseAllPendingPageCaches() for more information.
1121 Page* page = _private->page;
1125 if (_private->hasSpellCheckerDocumentTag) {
1126 [[NSSpellChecker sharedSpellChecker] closeSpellDocumentWithTag:_private->spellCheckerDocumentTag];
1127 _private->hasSpellCheckerDocumentTag = NO;
1130 #if USE(ACCELERATED_COMPOSITING)
1131 [self _clearLayerSyncLoopObserver];
1134 #if ENABLE(VIDEO) && USE(GSTREAMER)
1135 [self _clearGlibLoopObserver];
1138 [[NSDistributedNotificationCenter defaultCenter] removeObserver:self];
1139 [[NSNotificationCenter defaultCenter] removeObserver:self];
1141 [WebPreferences _removeReferenceForIdentifier:[self preferencesIdentifier]];
1143 WebPreferences *preferences = _private->preferences;
1144 _private->preferences = nil;
1145 [preferences didRemoveFromWebView];
1146 [preferences release];
1148 [self _closePluginDatabases];
1151 // Need this to make leak messages accurate.
1152 if (applicationIsTerminating) {
1153 gcController().garbageCollectNow();
1154 [WebCache setDisabled:YES];
1159 // Indicates if the WebView is in the midst of a user gesture.
1160 - (BOOL)_isProcessingUserGesture
1162 WebFrame *frame = [self mainFrame];
1163 return core(frame)->loader()->isProcessingUserGesture();
1166 + (NSString *)_MIMETypeForFile:(NSString *)path
1168 NSString *extension = [path pathExtension];
1169 NSString *MIMEType = nil;
1171 // Get the MIME type from the extension.
1172 if ([extension length] != 0) {
1173 MIMEType = WKGetMIMETypeForExtension(extension);
1176 // If we can't get a known MIME type from the extension, sniff.
1177 if ([MIMEType length] == 0 || [MIMEType isEqualToString:@"application/octet-stream"]) {
1178 NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:path];
1179 NSData *data = [handle readDataOfLength:WEB_GUESS_MIME_TYPE_PEEK_LENGTH];
1181 if ([data length] != 0) {
1182 MIMEType = [data _webkit_guessedMIMEType];
1184 if ([MIMEType length] == 0) {
1185 MIMEType = @"application/octet-stream";
1192 - (WebDownload *)_downloadURL:(NSURL *)URL
1196 NSURLRequest *request = [[NSURLRequest alloc] initWithURL:URL];
1197 WebDownload *download = [WebDownload _downloadWithRequest:request
1198 delegate:_private->downloadDelegate
1205 - (WebView *)_openNewWindowWithRequest:(NSURLRequest *)request
1207 NSDictionary *features = [[NSDictionary alloc] init];
1208 WebView *newWindowWebView = [[self _UIDelegateForwarder] webView:self
1209 createWebViewWithRequest:nil
1210 windowFeatures:features];
1212 if (!newWindowWebView)
1215 CallUIDelegate(newWindowWebView, @selector(webViewShow:));
1216 return newWindowWebView;
1219 - (WebInspector *)inspector
1221 if (!_private->inspector)
1222 _private->inspector = [[WebInspector alloc] initWithWebView:self];
1223 return _private->inspector;
1226 - (WebCore::Page*)page
1228 return _private->page;
1231 - (NSMenu *)_menuForElement:(NSDictionary *)element defaultItems:(NSArray *)items
1233 NSArray *defaultMenuItems = [[WebDefaultUIDelegate sharedUIDelegate] webView:self contextMenuItemsForElement:element defaultMenuItems:items];
1235 NSArray *menuItems = CallUIDelegate(self, @selector(webView:contextMenuItemsForElement:defaultMenuItems:), element, defaultMenuItems);
1239 unsigned count = [menuItems count];
1243 NSMenu *menu = [[NSMenu alloc] init];
1244 for (unsigned i = 0; i < count; i++)
1245 [menu addItem:[menuItems objectAtIndex:i]];
1247 return [menu autorelease];
1250 - (void)_mouseDidMoveOverElement:(NSDictionary *)dictionary modifierFlags:(NSUInteger)modifierFlags
1252 // We originally intended to call this delegate method sometimes with a nil dictionary, but due to
1253 // a bug dating back to WebKit 1.0 this delegate was never called with nil! Unfortunately we can't
1254 // start calling this with nil since it will break Adobe Help Viewer, and possibly other clients.
1257 CallUIDelegate(self, @selector(webView:mouseDidMoveOverElement:modifierFlags:), dictionary, modifierFlags);
1260 - (void)_loadBackForwardListFromOtherView:(WebView *)otherView
1262 if (!_private->page)
1265 if (!otherView->_private->page)
1268 // It turns out the right combination of behavior is done with the back/forward load
1269 // type. (See behavior matrix at the top of WebFramePrivate.) So we copy all the items
1270 // in the back forward list, and go to the current one.
1272 BackForwardList* backForwardList = _private->page->backForwardList();
1273 ASSERT(!backForwardList->currentItem()); // destination list should be empty
1275 BackForwardList* otherBackForwardList = otherView->_private->page->backForwardList();
1276 if (!otherBackForwardList->currentItem())
1277 return; // empty back forward list, bail
1279 HistoryItem* newItemToGoTo = 0;
1281 int lastItemIndex = otherBackForwardList->forwardListCount();
1282 for (int i = -otherBackForwardList->backListCount(); i <= lastItemIndex; ++i) {
1284 // If this item is showing , save away its current scroll and form state,
1285 // since that might have changed since loading and it is normally not saved
1286 // until we leave that page.
1287 otherView->_private->page->mainFrame()->loader()->history()->saveDocumentAndScrollState();
1289 RefPtr<HistoryItem> newItem = otherBackForwardList->itemAtIndex(i)->copy();
1291 newItemToGoTo = newItem.get();
1292 backForwardList->addItem(newItem.release());
1295 ASSERT(newItemToGoTo);
1296 _private->page->goToItem(newItemToGoTo, FrameLoadTypeIndexedBackForward);
1299 - (void)_setFormDelegate: (id<WebFormDelegate>)delegate
1301 _private->formDelegate = delegate;
1304 - (id<WebFormDelegate>)_formDelegate
1306 return _private->formDelegate;
1309 - (BOOL)_needsAdobeFrameReloadingQuirk
1311 static BOOL needsQuirk = WKAppVersionCheckLessThan(@"com.adobe.Acrobat", -1, 9.0)
1312 || WKAppVersionCheckLessThan(@"com.adobe.Acrobat.Pro", -1, 9.0)
1313 || WKAppVersionCheckLessThan(@"com.adobe.Reader", -1, 9.0)
1314 || WKAppVersionCheckLessThan(@"com.adobe.distiller", -1, 9.0)
1315 || WKAppVersionCheckLessThan(@"com.adobe.Contribute", -1, 4.2)
1316 || WKAppVersionCheckLessThan(@"com.adobe.dreamweaver-9.0", -1, 9.1)
1317 || WKAppVersionCheckLessThan(@"com.macromedia.fireworks", -1, 9.1)
1318 || WKAppVersionCheckLessThan(@"com.adobe.InCopy", -1, 5.1)
1319 || WKAppVersionCheckLessThan(@"com.adobe.InDesign", -1, 5.1)
1320 || WKAppVersionCheckLessThan(@"com.adobe.Soundbooth", -1, 2);
1325 - (BOOL)_needsLinkElementTextCSSQuirk
1327 static BOOL needsQuirk = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_LINK_ELEMENT_TEXT_CSS_QUIRK)
1328 && WKAppVersionCheckLessThan(@"com.e-frontier.shade10", -1, 10.6);
1332 - (BOOL)_needsKeyboardEventDisambiguationQuirks
1334 static BOOL needsQuirks = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_IE_COMPATIBLE_KEYBOARD_EVENT_DISPATCH) && !applicationIsSafari();
1338 - (BOOL)_needsFrameLoadDelegateRetainQuirk
1340 static BOOL needsQuirk = WKAppVersionCheckLessThan(@"com.equinux.iSale5", -1, 5.6);
1344 - (void)_preferencesChangedNotification:(NSNotification *)notification
1346 WebPreferences *preferences = (WebPreferences *)[notification object];
1347 ASSERT(preferences == [self preferences]);
1349 if (!_private->userAgentOverridden)
1350 _private->userAgent = String();
1352 // Cache this value so we don't have to read NSUserDefaults on each page load
1353 _private->useSiteSpecificSpoofing = [preferences _useSiteSpecificSpoofing];
1355 // Update corresponding WebCore Settings object.
1356 if (!_private->page)
1359 Settings* settings = _private->page->settings();
1361 settings->setCursiveFontFamily([preferences cursiveFontFamily]);
1362 settings->setDefaultFixedFontSize([preferences defaultFixedFontSize]);
1363 settings->setDefaultFontSize([preferences defaultFontSize]);
1364 settings->setDefaultTextEncodingName([preferences defaultTextEncodingName]);
1365 settings->setUsesEncodingDetector([preferences usesEncodingDetector]);
1366 settings->setFantasyFontFamily([preferences fantasyFontFamily]);
1367 settings->setFixedFontFamily([preferences fixedFontFamily]);
1368 settings->setForceFTPDirectoryListings([preferences _forceFTPDirectoryListings]);
1369 settings->setFTPDirectoryTemplatePath([preferences _ftpDirectoryTemplatePath]);
1370 settings->setLocalStorageDatabasePath([preferences _localStorageDatabasePath]);
1371 settings->setJavaEnabled([preferences isJavaEnabled]);
1372 settings->setJavaScriptEnabled([preferences isJavaScriptEnabled]);
1373 settings->setWebSecurityEnabled([preferences isWebSecurityEnabled]);
1374 settings->setAllowUniversalAccessFromFileURLs([preferences allowUniversalAccessFromFileURLs]);
1375 settings->setAllowFileAccessFromFileURLs([preferences allowFileAccessFromFileURLs]);
1376 settings->setJavaScriptCanOpenWindowsAutomatically([preferences javaScriptCanOpenWindowsAutomatically]);
1377 settings->setMinimumFontSize([preferences minimumFontSize]);
1378 settings->setMinimumLogicalFontSize([preferences minimumLogicalFontSize]);
1379 settings->setPluginsEnabled([preferences arePlugInsEnabled]);
1380 #if ENABLE(DATABASE)
1381 AbstractDatabase::setIsAvailable([preferences databasesEnabled]);
1383 settings->setLocalStorageEnabled([preferences localStorageEnabled]);
1384 settings->setExperimentalNotificationsEnabled([preferences experimentalNotificationsEnabled]);
1385 settings->setPrivateBrowsingEnabled([preferences privateBrowsingEnabled]);
1386 settings->setSansSerifFontFamily([preferences sansSerifFontFamily]);
1387 settings->setSerifFontFamily([preferences serifFontFamily]);
1388 settings->setStandardFontFamily([preferences standardFontFamily]);
1389 settings->setLoadsImagesAutomatically([preferences loadsImagesAutomatically]);
1390 settings->setShouldPrintBackgrounds([preferences shouldPrintBackgrounds]);
1391 settings->setTextAreasAreResizable([preferences textAreasAreResizable]);
1392 settings->setShrinksStandaloneImagesToFit([preferences shrinksStandaloneImagesToFit]);
1393 settings->setEditableLinkBehavior(core([preferences editableLinkBehavior]));
1394 settings->setEditingBehaviorType(core([preferences editingBehavior]));
1395 settings->setTextDirectionSubmenuInclusionBehavior(core([preferences textDirectionSubmenuInclusionBehavior]));
1396 settings->setDOMPasteAllowed([preferences isDOMPasteAllowed]);
1397 settings->setUsesPageCache([self usesPageCache]);
1398 settings->setShowsURLsInToolTips([preferences showsURLsInToolTips]);
1399 settings->setDeveloperExtrasEnabled([preferences developerExtrasEnabled]);
1400 settings->setAuthorAndUserStylesEnabled([preferences authorAndUserStylesEnabled]);
1401 settings->setApplicationChromeMode([preferences applicationChromeModeEnabled]);
1402 if ([preferences userStyleSheetEnabled]) {
1403 NSString* location = [[preferences userStyleSheetLocation] _web_originalDataAsString];
1404 if ([location isEqualToString:@"apple-dashboard://stylesheet"])
1405 location = @"file:///System/Library/PrivateFrameworks/DashboardClient.framework/Resources/widget.css";
1406 settings->setUserStyleSheetLocation([NSURL URLWithString:(location ? location : @"")]);
1408 settings->setUserStyleSheetLocation([NSURL URLWithString:@""]);
1409 settings->setNeedsAdobeFrameReloadingQuirk([self _needsAdobeFrameReloadingQuirk]);
1410 settings->setTreatsAnyTextCSSLinkAsStylesheet([self _needsLinkElementTextCSSQuirk]);
1411 settings->setNeedsKeyboardEventDisambiguationQuirks([self _needsKeyboardEventDisambiguationQuirks]);
1412 settings->setNeedsLeopardMailQuirks(runningLeopardMail());
1413 settings->setNeedsTigerMailQuirks(runningTigerMail());
1414 settings->setNeedsSiteSpecificQuirks(_private->useSiteSpecificSpoofing);
1415 settings->setWebArchiveDebugModeEnabled([preferences webArchiveDebugModeEnabled]);
1416 settings->setLocalFileContentSniffingEnabled([preferences localFileContentSniffingEnabled]);
1417 settings->setOfflineWebApplicationCacheEnabled([preferences offlineWebApplicationCacheEnabled]);
1418 settings->setZoomMode([preferences zoomsTextOnly] ? ZoomTextOnly : ZoomPage);
1419 settings->setJavaScriptCanAccessClipboard([preferences javaScriptCanAccessClipboard]);
1420 settings->setXSSAuditorEnabled([preferences isXSSAuditorEnabled]);
1421 settings->setEnforceCSSMIMETypeInStrictMode(!WKAppVersionCheckLessThan(@"com.apple.iWeb", -1, 2.1));
1422 settings->setDNSPrefetchingEnabled([preferences isDNSPrefetchingEnabled]);
1424 // FIXME: Enabling accelerated compositing when WebGL is enabled causes tests to fail on Leopard which expect HW compositing to be disabled.
1425 // Until we fix that, I will comment out the test (CFM)
1426 settings->setAcceleratedCompositingEnabled((coreVideoHas7228836Fix() || [preferences webGLEnabled]) && [preferences acceleratedCompositingEnabled]);
1427 settings->setShowDebugBorders([preferences showDebugBorders]);
1428 settings->setShowRepaintCounter([preferences showRepaintCounter]);
1429 settings->setPluginAllowedRunTime([preferences pluginAllowedRunTime]);
1430 settings->setWebGLEnabled([preferences webGLEnabled]);
1431 settings->setLoadDeferringEnabled(shouldEnableLoadDeferring());
1432 settings->setFrameFlatteningEnabled([preferences isFrameFlatteningEnabled]);
1433 settings->setHTML5ParserEnabled([preferences html5ParserEnabled]);
1434 settings->setHTML5TreeBuilderEnabled_DO_NOT_USE([preferences html5TreeBuilderEnabled]);
1435 settings->setPaginateDuringLayoutEnabled([preferences paginateDuringLayoutEnabled]);
1438 static inline IMP getMethod(id o, SEL s)
1440 return [o respondsToSelector:s] ? [o methodForSelector:s] : 0;
1443 - (void)_cacheResourceLoadDelegateImplementations
1445 WebResourceDelegateImplementationCache *cache = &_private->resourceLoadDelegateImplementations;
1446 id delegate = _private->resourceProgressDelegate;
1449 bzero(cache, sizeof(WebResourceDelegateImplementationCache));
1453 cache->didCancelAuthenticationChallengeFunc = getMethod(delegate, @selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:));
1454 cache->didFailLoadingWithErrorFromDataSourceFunc = getMethod(delegate, @selector(webView:resource:didFailLoadingWithError:fromDataSource:));
1455 cache->didFinishLoadingFromDataSourceFunc = getMethod(delegate, @selector(webView:resource:didFinishLoadingFromDataSource:));
1456 cache->didLoadResourceFromMemoryCacheFunc = getMethod(delegate, @selector(webView:didLoadResourceFromMemoryCache:response:length:fromDataSource:));
1457 cache->didReceiveAuthenticationChallengeFunc = getMethod(delegate, @selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:));
1458 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
1459 cache->canAuthenticateAgainstProtectionSpaceFunc = getMethod(delegate, @selector(webView:resource:canAuthenticateAgainstProtectionSpace:forDataSource:));
1461 cache->didReceiveContentLengthFunc = getMethod(delegate, @selector(webView:resource:didReceiveContentLength:fromDataSource:));
1462 cache->didReceiveResponseFunc = getMethod(delegate, @selector(webView:resource:didReceiveResponse:fromDataSource:));
1463 cache->identifierForRequestFunc = getMethod(delegate, @selector(webView:identifierForInitialRequest:fromDataSource:));
1464 cache->plugInFailedWithErrorFunc = getMethod(delegate, @selector(webView:plugInFailedWithError:dataSource:));
1465 cache->willCacheResponseFunc = getMethod(delegate, @selector(webView:resource:willCacheResponse:fromDataSource:));
1466 cache->willSendRequestFunc = getMethod(delegate, @selector(webView:resource:willSendRequest:redirectResponse:fromDataSource:));
1467 cache->shouldUseCredentialStorageFunc = getMethod(delegate, @selector(webView:resource:shouldUseCredentialStorageForDataSource:));
1470 - (void)_cacheFrameLoadDelegateImplementations
1472 WebFrameLoadDelegateImplementationCache *cache = &_private->frameLoadDelegateImplementations;
1473 id delegate = _private->frameLoadDelegate;
1476 bzero(cache, sizeof(WebFrameLoadDelegateImplementationCache));
1480 cache->didCancelClientRedirectForFrameFunc = getMethod(delegate, @selector(webView:didCancelClientRedirectForFrame:));
1481 cache->didChangeLocationWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didChangeLocationWithinPageForFrame:));
1482 cache->didPushStateWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didPushStateWithinPageForFrame:));
1483 cache->didReplaceStateWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didReplaceStateWithinPageForFrame:));
1484 cache->didPopStateWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didPopStateWithinPageForFrame:));
1485 cache->didClearWindowObjectForFrameFunc = getMethod(delegate, @selector(webView:didClearWindowObject:forFrame:));
1486 cache->didClearWindowObjectForFrameInScriptWorldFunc = getMethod(delegate, @selector(webView:didClearWindowObjectForFrame:inScriptWorld:));
1487 cache->didClearInspectorWindowObjectForFrameFunc = getMethod(delegate, @selector(webView:didClearInspectorWindowObject:forFrame:));
1488 cache->didCommitLoadForFrameFunc = getMethod(delegate, @selector(webView:didCommitLoadForFrame:));
1489 cache->didFailLoadWithErrorForFrameFunc = getMethod(delegate, @selector(webView:didFailLoadWithError:forFrame:));
1490 cache->didFailProvisionalLoadWithErrorForFrameFunc = getMethod(delegate, @selector(webView:didFailProvisionalLoadWithError:forFrame:));
1491 cache->didFinishDocumentLoadForFrameFunc = getMethod(delegate, @selector(webView:didFinishDocumentLoadForFrame:));
1492 cache->didFinishLoadForFrameFunc = getMethod(delegate, @selector(webView:didFinishLoadForFrame:));
1493 cache->didFirstLayoutInFrameFunc = getMethod(delegate, @selector(webView:didFirstLayoutInFrame:));
1494 cache->didFirstVisuallyNonEmptyLayoutInFrameFunc = getMethod(delegate, @selector(webView:didFirstVisuallyNonEmptyLayoutInFrame:));
1495 cache->didHandleOnloadEventsForFrameFunc = getMethod(delegate, @selector(webView:didHandleOnloadEventsForFrame:));
1496 cache->didReceiveIconForFrameFunc = getMethod(delegate, @selector(webView:didReceiveIcon:forFrame:));
1497 cache->didReceiveServerRedirectForProvisionalLoadForFrameFunc = getMethod(delegate, @selector(webView:didReceiveServerRedirectForProvisionalLoadForFrame:));
1498 cache->didReceiveTitleForFrameFunc = getMethod(delegate, @selector(webView:didReceiveTitle:forFrame:));
1499 cache->didStartProvisionalLoadForFrameFunc = getMethod(delegate, @selector(webView:didStartProvisionalLoadForFrame:));
1500 cache->willCloseFrameFunc = getMethod(delegate, @selector(webView:willCloseFrame:));
1501 cache->willPerformClientRedirectToURLDelayFireDateForFrameFunc = getMethod(delegate, @selector(webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:));
1502 cache->windowScriptObjectAvailableFunc = getMethod(delegate, @selector(webView:windowScriptObjectAvailable:));
1503 cache->didDisplayInsecureContentFunc = getMethod(delegate, @selector(webViewDidDisplayInsecureContent:));
1504 cache->didRunInsecureContentFunc = getMethod(delegate, @selector(webView:didRunInsecureContent:));
1507 - (void)_cacheScriptDebugDelegateImplementations
1509 WebScriptDebugDelegateImplementationCache *cache = &_private->scriptDebugDelegateImplementations;
1510 id delegate = _private->scriptDebugDelegate;
1513 bzero(cache, sizeof(WebScriptDebugDelegateImplementationCache));
1517 cache->didParseSourceFunc = getMethod(delegate, @selector(webView:didParseSource:baseLineNumber:fromURL:sourceId:forWebFrame:));
1518 if (cache->didParseSourceFunc)
1519 cache->didParseSourceExpectsBaseLineNumber = YES;
1521 cache->didParseSourceFunc = getMethod(delegate, @selector(webView:didParseSource:fromURL:sourceId:forWebFrame:));
1523 cache->failedToParseSourceFunc = getMethod(delegate, @selector(webView:failedToParseSource:baseLineNumber:fromURL:withError:forWebFrame:));
1524 cache->didEnterCallFrameFunc = getMethod(delegate, @selector(webView:didEnterCallFrame:sourceId:line:forWebFrame:));
1525 cache->willExecuteStatementFunc = getMethod(delegate, @selector(webView:willExecuteStatement:sourceId:line:forWebFrame:));
1526 cache->willLeaveCallFrameFunc = getMethod(delegate, @selector(webView:willLeaveCallFrame:sourceId:line:forWebFrame:));
1527 cache->exceptionWasRaisedFunc = getMethod(delegate, @selector(webView:exceptionWasRaised:sourceId:line:forWebFrame:));
1530 - (void)_cacheHistoryDelegateImplementations
1532 WebHistoryDelegateImplementationCache *cache = &_private->historyDelegateImplementations;
1533 id delegate = _private->historyDelegate;
1536 bzero(cache, sizeof(WebHistoryDelegateImplementationCache));
1540 cache->navigatedFunc = getMethod(delegate, @selector(webView:didNavigateWithNavigationData:inFrame:));
1541 cache->clientRedirectFunc = getMethod(delegate, @selector(webView:didPerformClientRedirectFromURL:toURL:inFrame:));
1542 cache->serverRedirectFunc = getMethod(delegate, @selector(webView:didPerformServerRedirectFromURL:toURL:inFrame:));
1543 cache->setTitleFunc = getMethod(delegate, @selector(webView:updateHistoryTitle:forURL:));
1544 cache->populateVisitedLinksFunc = getMethod(delegate, @selector(populateVisitedLinksForWebView:));
1547 - (id)_policyDelegateForwarder
1549 if (!_private->policyDelegateForwarder)
1550 _private->policyDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->policyDelegate defaultTarget:[WebDefaultPolicyDelegate sharedPolicyDelegate] catchExceptions:_private->catchesDelegateExceptions];
1551 return _private->policyDelegateForwarder;
1554 - (id)_UIDelegateForwarder
1556 if (!_private->UIDelegateForwarder)
1557 _private->UIDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->UIDelegate defaultTarget:[WebDefaultUIDelegate sharedUIDelegate] catchExceptions:_private->catchesDelegateExceptions];
1558 return _private->UIDelegateForwarder;
1561 - (id)_editingDelegateForwarder
1563 // This can be called during window deallocation by QTMovieView in the QuickTime Cocoa Plug-in.
1564 // Not sure if that is a bug or not.
1568 if (!_private->editingDelegateForwarder)
1569 _private->editingDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->editingDelegate defaultTarget:[WebDefaultEditingDelegate sharedEditingDelegate] catchExceptions:_private->catchesDelegateExceptions];
1570 return _private->editingDelegateForwarder;
1573 - (void)_closeWindow
1575 [[self _UIDelegateForwarder] webViewClose:self];
1578 + (void)_unregisterViewClassAndRepresentationClassForMIMEType:(NSString *)MIMEType
1580 [[WebFrameView _viewTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType];
1581 [[WebDataSource _repTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType];
1583 // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
1584 // in the WebCore MIMEType registry. For now we're doing this in a safe, limited manner
1585 // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
1586 MIMETypeRegistry::getSupportedNonImageMIMETypes().remove(MIMEType);
1589 + (void)_registerViewClass:(Class)viewClass representationClass:(Class)representationClass forURLScheme:(NSString *)URLScheme
1591 NSString *MIMEType = [self _generatedMIMETypeForURLScheme:URLScheme];
1592 [self registerViewClass:viewClass representationClass:representationClass forMIMEType:MIMEType];
1594 // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
1595 // in the WebCore MIMEType registry. For now we're doing this in a safe, limited manner
1596 // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
1597 if ([viewClass class] == [WebHTMLView class])
1598 MIMETypeRegistry::getSupportedNonImageMIMETypes().add(MIMEType);
1600 // This is used to make _representationExistsForURLScheme faster.
1601 // Without this set, we'd have to create the MIME type each time.
1602 if (schemesWithRepresentationsSet == nil) {
1603 schemesWithRepresentationsSet = [[NSMutableSet alloc] init];
1605 [schemesWithRepresentationsSet addObject:[[[URLScheme lowercaseString] copy] autorelease]];
1608 + (NSString *)_generatedMIMETypeForURLScheme:(NSString *)URLScheme
1610 return [@"x-apple-web-kit/" stringByAppendingString:[URLScheme lowercaseString]];
1613 + (BOOL)_representationExistsForURLScheme:(NSString *)URLScheme
1615 return [schemesWithRepresentationsSet containsObject:[URLScheme lowercaseString]];
1618 + (BOOL)_canHandleRequest:(NSURLRequest *)request forMainFrame:(BOOL)forMainFrame
1620 // FIXME: If <rdar://problem/5217309> gets fixed, this check can be removed.
1624 if ([NSURLConnection canHandleRequest:request])
1627 NSString *scheme = [[request URL] scheme];
1629 // Representations for URL schemes work at the top level.
1630 if (forMainFrame && [self _representationExistsForURLScheme:scheme])
1633 return [scheme _webkit_isCaseInsensitiveEqualToString:@"applewebdata"];
1636 + (BOOL)_canHandleRequest:(NSURLRequest *)request
1638 return [self _canHandleRequest:request forMainFrame:YES];
1641 + (NSString *)_decodeData:(NSData *)data
1643 HTMLNames::init(); // this method is used for importing bookmarks at startup, so HTMLNames are likely to be uninitialized yet
1644 RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("text/html"); // bookmark files are HTML
1645 String result = decoder->decode(static_cast<const char*>([data bytes]), [data length]);
1646 result += decoder->flush();
1650 - (void)_pushPerformingProgrammaticFocus
1652 _private->programmaticFocusCount++;
1655 - (void)_popPerformingProgrammaticFocus
1657 _private->programmaticFocusCount--;
1660 - (BOOL)_isPerformingProgrammaticFocus
1662 return _private->programmaticFocusCount != 0;
1665 - (void)_didChangeValueForKey: (NSString *)key
1667 LOG (Bindings, "calling didChangeValueForKey: %@", key);
1668 [self didChangeValueForKey: key];
1671 - (void)_willChangeValueForKey: (NSString *)key
1673 LOG (Bindings, "calling willChangeValueForKey: %@", key);
1674 [self willChangeValueForKey: key];
1677 + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key {
1678 static NSSet *manualNotifyKeys = nil;
1679 if (!manualNotifyKeys)
1680 manualNotifyKeys = [[NSSet alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey,
1681 _WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, _WebMainFrameDocumentKey,
1683 if ([manualNotifyKeys containsObject:key])
1688 - (NSArray *)_declaredKeys {
1689 static NSArray *declaredKeys = nil;
1691 declaredKeys = [[NSArray alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey,
1692 _WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, _WebMainFrameDocumentKey, nil];
1693 return declaredKeys;
1696 - (void)setObservationInfo:(void *)info
1698 _private->observationInfo = info;
1701 - (void *)observationInfo
1703 return _private->observationInfo;
1706 - (void)_willChangeBackForwardKeys
1708 [self _willChangeValueForKey: _WebCanGoBackKey];
1709 [self _willChangeValueForKey: _WebCanGoForwardKey];
1712 - (void)_didChangeBackForwardKeys
1714 [self _didChangeValueForKey: _WebCanGoBackKey];
1715 [self _didChangeValueForKey: _WebCanGoForwardKey];
1718 - (void)_didStartProvisionalLoadForFrame:(WebFrame *)frame
1720 [self _willChangeBackForwardKeys];
1721 if (frame == [self mainFrame]){
1722 // Force an observer update by sending a will/did.
1723 [self _willChangeValueForKey: _WebIsLoadingKey];
1724 [self _didChangeValueForKey: _WebIsLoadingKey];
1726 [self _willChangeValueForKey: _WebMainFrameURLKey];
1729 [NSApp setWindowsNeedUpdate:YES];
1732 - (void)_didCommitLoadForFrame:(WebFrame *)frame
1734 if (frame == [self mainFrame])
1735 [self _didChangeValueForKey: _WebMainFrameURLKey];
1736 [NSApp setWindowsNeedUpdate:YES];
1739 - (void)_didFinishLoadForFrame:(WebFrame *)frame
1741 [self _didChangeBackForwardKeys];
1742 if (frame == [self mainFrame]){
1743 // Force an observer update by sending a will/did.
1744 [self _willChangeValueForKey: _WebIsLoadingKey];
1745 [self _didChangeValueForKey: _WebIsLoadingKey];
1747 [NSApp setWindowsNeedUpdate:YES];
1750 - (void)_didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
1752 [self _didChangeBackForwardKeys];
1753 if (frame == [self mainFrame]){
1754 // Force an observer update by sending a will/did.
1755 [self _willChangeValueForKey: _WebIsLoadingKey];
1756 [self _didChangeValueForKey: _WebIsLoadingKey];
1758 [NSApp setWindowsNeedUpdate:YES];
1761 - (void)_didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
1763 [self _didChangeBackForwardKeys];
1764 if (frame == [self mainFrame]){
1765 // Force an observer update by sending a will/did.
1766 [self _willChangeValueForKey: _WebIsLoadingKey];
1767 [self _didChangeValueForKey: _WebIsLoadingKey];
1769 [self _didChangeValueForKey: _WebMainFrameURLKey];
1771 [NSApp setWindowsNeedUpdate:YES];
1774 - (NSCachedURLResponse *)_cachedResponseForURL:(NSURL *)URL
1776 NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:URL];
1777 [request _web_setHTTPUserAgent:[self userAgentForURL:URL]];
1778 NSCachedURLResponse *cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:request];
1780 return cachedResponse;
1783 - (void)_writeImageForElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
1785 NSURL *linkURL = [element objectForKey:WebElementLinkURLKey];
1786 DOMElement *domElement = [element objectForKey:WebElementDOMNodeKey];
1787 [pasteboard _web_writeImage:(NSImage *)(domElement ? nil : [element objectForKey:WebElementImageKey])
1789 URL:linkURL ? linkURL : (NSURL *)[element objectForKey:WebElementImageURLKey]
1790 title:[element objectForKey:WebElementImageAltStringKey]
1791 archive:[[element objectForKey:WebElementDOMNodeKey] webArchive]
1796 - (void)_writeLinkElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
1798 [pasteboard _web_writeURL:[element objectForKey:WebElementLinkURLKey]
1799 andTitle:[element objectForKey:WebElementLinkLabelKey]
1803 - (void)_setInitiatedDrag:(BOOL)initiatedDrag
1805 if (!_private->page)
1807 _private->page->dragController()->setDidInitiateDrag(initiatedDrag);
1810 #if ENABLE(DASHBOARD_SUPPORT)
1812 #define DASHBOARD_CONTROL_LABEL @"control"
1814 - (void)_addControlRect:(NSRect)bounds clip:(NSRect)clip fromView:(NSView *)view toDashboardRegions:(NSMutableDictionary *)regions
1816 NSRect adjustedBounds = bounds;
1817 adjustedBounds.origin = [self convertPoint:bounds.origin fromView:view];
1818 adjustedBounds.origin.y = [self bounds].size.height - adjustedBounds.origin.y;
1819 adjustedBounds.size = bounds.size;
1821 NSRect adjustedClip;
1822 adjustedClip.origin = [self convertPoint:clip.origin fromView:view];
1823 adjustedClip.origin.y = [self bounds].size.height - adjustedClip.origin.y;
1824 adjustedClip.size = clip.size;
1826 WebDashboardRegion *region = [[WebDashboardRegion alloc] initWithRect:adjustedBounds
1827 clip:adjustedClip type:WebDashboardRegionTypeScrollerRectangle];
1828 NSMutableArray *scrollerRegions = [regions objectForKey:DASHBOARD_CONTROL_LABEL];
1829 if (!scrollerRegions) {
1830 scrollerRegions = [[NSMutableArray alloc] init];
1831 [regions setObject:scrollerRegions forKey:DASHBOARD_CONTROL_LABEL];
1832 [scrollerRegions release];
1834 [scrollerRegions addObject:region];
1838 - (void)_addScrollerDashboardRegionsForFrameView:(FrameView*)frameView dashboardRegions:(NSMutableDictionary *)regions
1840 NSView *documentView = [[kit(frameView->frame()) frameView] documentView];
1842 const HashSet<RefPtr<Widget> >* children = frameView->children();
1843 HashSet<RefPtr<Widget> >::const_iterator end = children->end();
1844 for (HashSet<RefPtr<Widget> >::const_iterator it = children->begin(); it != end; ++it) {
1845 Widget* widget = (*it).get();
1846 if (widget->isFrameView()) {
1847 [self _addScrollerDashboardRegionsForFrameView:static_cast<FrameView*>(widget) dashboardRegions:regions];
1851 if (!widget->isScrollbar())
1854 // FIXME: This should really pass an appropriate clip, but our first try got it wrong, and
1855 // it's not common to need this to be correct in Dashboard widgets.
1856 NSRect bounds = widget->frameRect();
1857 [self _addControlRect:bounds clip:bounds fromView:documentView toDashboardRegions:regions];
1861 - (void)_addScrollerDashboardRegions:(NSMutableDictionary *)regions from:(NSArray *)views
1863 // Add scroller regions for NSScroller and WebCore scrollbars
1864 NSUInteger count = [views count];
1865 for (NSUInteger i = 0; i < count; i++) {
1866 NSView *view = [views objectAtIndex:i];
1868 if ([view isKindOfClass:[WebHTMLView class]]) {
1869 if (Frame* coreFrame = core([(WebHTMLView*)view _frame])) {
1870 if (FrameView* coreView = coreFrame->view())
1871 [self _addScrollerDashboardRegionsForFrameView:coreView dashboardRegions:regions];
1873 } else if ([view isKindOfClass:[NSScroller class]]) {
1874 // AppKit places absent scrollers at -100,-100
1875 if ([view frame].origin.y < 0)
1877 [self _addControlRect:[view bounds] clip:[view visibleRect] fromView:view toDashboardRegions:regions];
1879 [self _addScrollerDashboardRegions:regions from:[view subviews]];
1883 - (void)_addScrollerDashboardRegions:(NSMutableDictionary *)regions
1885 [self _addScrollerDashboardRegions:regions from:[self subviews]];
1888 - (NSDictionary *)_dashboardRegions
1890 // Only return regions from main frame.
1891 Frame* mainFrame = [self _mainCoreFrame];
1894 NSMutableDictionary *regions = mainFrame->dashboardRegionsDictionary();
1895 [self _addScrollerDashboardRegions:regions];
1899 - (void)_setDashboardBehavior:(WebDashboardBehavior)behavior to:(BOOL)flag
1901 // FIXME: Remove this blanket assignment once Dashboard and Dashcode implement
1902 // specific support for the backward compatibility mode flag.
1903 if (behavior == WebDashboardBehaviorAllowWheelScrolling && flag == NO && _private->page)
1904 _private->page->settings()->setUsesDashboardBackwardCompatibilityMode(true);
1907 case WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows: {
1908 _private->dashboardBehaviorAlwaysSendMouseEventsToAllWindows = flag;
1911 case WebDashboardBehaviorAlwaysSendActiveNullEventsToPlugIns: {
1912 _private->dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns = flag;
1915 case WebDashboardBehaviorAlwaysAcceptsFirstMouse: {
1916 _private->dashboardBehaviorAlwaysAcceptsFirstMouse = flag;
1919 case WebDashboardBehaviorAllowWheelScrolling: {
1920 _private->dashboardBehaviorAllowWheelScrolling = flag;
1923 case WebDashboardBehaviorUseBackwardCompatibilityMode: {
1925 _private->page->settings()->setUsesDashboardBackwardCompatibilityMode(flag);
1931 - (BOOL)_dashboardBehavior:(WebDashboardBehavior)behavior
1934 case WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows: {
1935 return _private->dashboardBehaviorAlwaysSendMouseEventsToAllWindows;
1937 case WebDashboardBehaviorAlwaysSendActiveNullEventsToPlugIns: {
1938 return _private->dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns;
1940 case WebDashboardBehaviorAlwaysAcceptsFirstMouse: {
1941 return _private->dashboardBehaviorAlwaysAcceptsFirstMouse;
1943 case WebDashboardBehaviorAllowWheelScrolling: {
1944 return _private->dashboardBehaviorAllowWheelScrolling;
1946 case WebDashboardBehaviorUseBackwardCompatibilityMode: {
1947 return _private->page && _private->page->settings()->usesDashboardBackwardCompatibilityMode();
1953 #endif /* ENABLE(DASHBOARD_SUPPORT) */
1955 + (void)_setShouldUseFontSmoothing:(BOOL)f
1957 Font::setShouldUseSmoothing(f);
1960 + (BOOL)_shouldUseFontSmoothing
1962 return Font::shouldUseSmoothing();
1965 + (void)_setUsesTestModeFocusRingColor:(BOOL)f
1967 setUsesTestModeFocusRingColor(f);
1970 + (BOOL)_usesTestModeFocusRingColor
1972 return usesTestModeFocusRingColor();
1975 - (void)setAlwaysShowVerticalScroller:(BOOL)flag
1977 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
1979 [scrollview setVerticalScrollingMode:ScrollbarAlwaysOn andLock:YES];
1981 [scrollview setVerticalScrollingModeLocked:NO];
1982 [scrollview setVerticalScrollingMode:ScrollbarAuto andLock:NO];
1986 - (BOOL)alwaysShowVerticalScroller
1988 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
1989 return [scrollview verticalScrollingModeLocked] && [scrollview verticalScrollingMode] == ScrollbarAlwaysOn;
1992 - (void)setAlwaysShowHorizontalScroller:(BOOL)flag
1994 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
1996 [scrollview setHorizontalScrollingMode:ScrollbarAlwaysOn andLock:YES];
1998 [scrollview setHorizontalScrollingModeLocked:NO];
1999 [scrollview setHorizontalScrollingMode:ScrollbarAuto andLock:NO];
2003 - (void)setProhibitsMainFrameScrolling:(BOOL)prohibits
2005 if (Frame* mainFrame = [self _mainCoreFrame])
2006 mainFrame->view()->setProhibitsScrolling(prohibits);
2009 - (BOOL)alwaysShowHorizontalScroller
2011 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
2012 return [scrollview horizontalScrollingModeLocked] && [scrollview horizontalScrollingMode] == ScrollbarAlwaysOn;
2015 - (void)_setInViewSourceMode:(BOOL)flag
2017 if (Frame* mainFrame = [self _mainCoreFrame])
2018 mainFrame->setInViewSourceMode(flag);
2021 - (BOOL)_inViewSourceMode
2023 Frame* mainFrame = [self _mainCoreFrame];
2024 return mainFrame && mainFrame->inViewSourceMode();
2027 - (void)_setUseFastImageScalingMode:(BOOL)flag
2029 if (_private->page && _private->page->inLowQualityImageInterpolationMode() != flag) {
2030 _private->page->setInLowQualityImageInterpolationMode(flag);
2031 [self setNeedsDisplay:YES];
2035 - (BOOL)_inFastImageScalingMode
2038 return _private->page->inLowQualityImageInterpolationMode();
2042 - (BOOL)_cookieEnabled
2045 return _private->page->cookieEnabled();
2049 - (void)_setCookieEnabled:(BOOL)enable
2052 _private->page->setCookieEnabled(enable);
2055 - (void)_setAdditionalWebPlugInPaths:(NSArray *)newPaths
2057 if (!_private->pluginDatabase)
2058 _private->pluginDatabase = [[WebPluginDatabase alloc] init];
2060 [_private->pluginDatabase setPlugInPaths:newPaths];
2061 [_private->pluginDatabase refresh];
2064 - (void)_attachScriptDebuggerToAllFrames
2066 for (Frame* frame = [self _mainCoreFrame]; frame; frame = frame->tree()->traverseNext())
2067 [kit(frame) _attachScriptDebugger];
2070 - (void)_detachScriptDebuggerFromAllFrames
2072 for (Frame* frame = [self _mainCoreFrame]; frame; frame = frame->tree()->traverseNext())
2073 [kit(frame) _detachScriptDebugger];
2076 - (void)setBackgroundColor:(NSColor *)backgroundColor
2078 if ([_private->backgroundColor isEqual:backgroundColor])
2081 id old = _private->backgroundColor;
2082 _private->backgroundColor = [backgroundColor retain];
2085 [[self mainFrame] _updateBackgroundAndUpdatesWhileOffscreen];
2088 - (NSColor *)backgroundColor
2090 return _private->backgroundColor;
2093 - (BOOL)defersCallbacks
2095 if (!_private->page)
2097 return _private->page->defersLoading();
2100 - (void)setDefersCallbacks:(BOOL)defer
2102 if (!_private->page)
2104 return _private->page->setDefersLoading(defer);
2107 // For backwards compatibility with the WebBackForwardList API, we honor both
2108 // a per-WebView and a per-preferences setting for whether to use the page cache.
2110 - (BOOL)usesPageCache
2112 return _private->usesPageCache && [[self preferences] usesPageCache];
2115 - (void)setUsesPageCache:(BOOL)usesPageCache
2117 _private->usesPageCache = usesPageCache;
2119 // Post a notification so the WebCore settings update.
2120 [[self preferences] _postPreferencesChangesNotification];
2123 - (WebHistoryItem *)_globalHistoryItem
2125 if (!_private->page)
2127 return kit(_private->page->globalHistoryItem());
2130 - (WebTextIterator *)textIteratorForRect:(NSRect)rect
2132 IntPoint rectStart(rect.origin.x, rect.origin.y);
2133 IntPoint rectEnd(rect.origin.x + rect.size.width, rect.origin.y + rect.size.height);
2135 Frame* coreFrame = [self _mainCoreFrame];
2139 VisibleSelection selectionInsideRect(coreFrame->visiblePositionForPoint(rectStart), coreFrame->visiblePositionForPoint(rectEnd));
2141 return [[[WebTextIterator alloc] initWithRange:kit(selectionInsideRect.toNormalizedRange().get())] autorelease];
2144 - (void)handleAuthenticationForResource:(id)identifier challenge:(NSURLAuthenticationChallenge *)challenge fromDataSource:(WebDataSource *)dataSource
2146 NSWindow *window = [self hostWindow] ? [self hostWindow] : [self window];
2147 [[WebPanelAuthenticationHandler sharedHandler] startAuthentication:challenge window:window];
2150 - (void)_clearUndoRedoOperations
2152 if (!_private->page)
2154 _private->page->clearUndoRedoOperations();
2157 - (void)_setCatchesDelegateExceptions:(BOOL)f
2159 _private->catchesDelegateExceptions = f;
2162 - (BOOL)_catchesDelegateExceptions
2164 return _private->catchesDelegateExceptions;
2167 - (void)_executeCoreCommandByName:(NSString *)name value:(NSString *)value
2169 Frame* coreFrame = [self _mainCoreFrame];
2172 coreFrame->editor()->command(name).execute(value);
2175 - (void)_setCustomHTMLTokenizerTimeDelay:(double)timeDelay
2177 if (!_private->page)
2179 return _private->page->setCustomHTMLTokenizerTimeDelay(timeDelay);
2182 - (void)_setCustomHTMLTokenizerChunkSize:(int)chunkSize
2184 if (!_private->page)
2186 return _private->page->setCustomHTMLTokenizerChunkSize(chunkSize);
2189 - (void)_clearMainFrameName
2191 _private->page->mainFrame()->tree()->clearName();
2194 - (void)setSelectTrailingWhitespaceEnabled:(BOOL)flag
2196 _private->selectTrailingWhitespaceEnabled = flag;
2198 [self setSmartInsertDeleteEnabled:false];
2201 - (BOOL)isSelectTrailingWhitespaceEnabled
2203 return _private->selectTrailingWhitespaceEnabled;
2206 - (void)setMemoryCacheDelegateCallsEnabled:(BOOL)enabled
2208 _private->page->setMemoryCacheClientCallsEnabled(enabled);
2211 - (BOOL)areMemoryCacheDelegateCallsEnabled
2213 return _private->page->areMemoryCacheClientCallsEnabled();
2216 - (void)_setJavaScriptURLsAreAllowed:(BOOL)areAllowed
2218 _private->page->setJavaScriptURLsAreAllowed(areAllowed);
2221 + (NSCursor *)_pointingHandCursor
2223 return handCursor().impl();
2226 - (BOOL)_postsAcceleratedCompositingNotifications
2228 #if USE(ACCELERATED_COMPOSITING)
2229 return _private->postsAcceleratedCompositingNotifications;
2235 - (void)_setPostsAcceleratedCompositingNotifications:(BOOL)flag
2237 #if USE(ACCELERATED_COMPOSITING)
2238 _private->postsAcceleratedCompositingNotifications = flag;
2242 - (BOOL)_isUsingAcceleratedCompositing
2244 #if USE(ACCELERATED_COMPOSITING)
2245 if (_private->usesDocumentViews) {
2246 Frame* coreFrame = [self _mainCoreFrame];
2247 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
2248 NSView *documentView = [[kit(frame) frameView] documentView];
2249 if ([documentView isKindOfClass:[WebHTMLView class]] && [(WebHTMLView *)documentView _isUsingAcceleratedCompositing])
2257 - (BOOL)_isSoftwareRenderable
2259 #if USE(ACCELERATED_COMPOSITING)
2260 if (_private->usesDocumentViews) {
2261 Frame* coreFrame = [self _mainCoreFrame];
2262 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
2263 if (FrameView* view = frame->view()) {
2264 if (!view->isSoftwareRenderable())
2273 - (void)_setIncludesFlattenedCompositingLayersWhenDrawingToBitmap:(BOOL)flag
2275 _private->includesFlattenedCompositingLayersWhenDrawingToBitmap = flag;
2278 - (BOOL)_includesFlattenedCompositingLayersWhenDrawingToBitmap
2280 return _private->includesFlattenedCompositingLayersWhenDrawingToBitmap;
2283 static WebBaseNetscapePluginView *_pluginViewForNode(DOMNode *node)
2288 Node* coreNode = core(node);
2292 RenderObject* renderer = coreNode->renderer();
2293 if (!renderer || !renderer->isWidget())
2296 Widget* widget = toRenderWidget(renderer)->widget();
2297 if (!widget || !widget->platformWidget())
2300 NSView *view = widget->platformWidget();
2301 if (![view isKindOfClass:[WebBaseNetscapePluginView class]])
2304 return (WebBaseNetscapePluginView *)view;
2307 + (BOOL)_isNodeHaltedPlugin:(DOMNode *)node
2309 return [_pluginViewForNode(node) isHalted];
2312 + (BOOL)_hasPluginForNodeBeenHalted:(DOMNode *)node
2314 return [_pluginViewForNode(node) hasBeenHalted];
2316 + (void)_restartHaltedPluginForNode:(DOMNode *)node
2321 [_pluginViewForNode(node) resumeFromHalt];
2324 - (NSPasteboard *)_insertionPasteboard
2326 return _private ? _private->insertionPasteboard : nil;
2329 + (void)_addOriginAccessWhitelistEntryWithSourceOrigin:(NSString *)sourceOrigin destinationProtocol:(NSString *)destinationProtocol destinationHost:(NSString *)destinationHost allowDestinationSubdomains:(BOOL)allowDestinationSubdomains
2331 SecurityOrigin::addOriginAccessWhitelistEntry(*SecurityOrigin::createFromString(sourceOrigin), destinationProtocol, destinationHost, allowDestinationSubdomains);
2334 + (void)_removeOriginAccessWhitelistEntryWithSourceOrigin:(NSString *)sourceOrigin destinationProtocol:(NSString *)destinationProtocol destinationHost:(NSString *)destinationHost allowDestinationSubdomains:(BOOL)allowDestinationSubdomains
2336 SecurityOrigin::removeOriginAccessWhitelistEntry(*SecurityOrigin::createFromString(sourceOrigin), destinationProtocol, destinationHost, allowDestinationSubdomains);
2339 +(void)_resetOriginAccessWhitelists
2341 SecurityOrigin::resetOriginAccessWhitelists();
2344 - (void)_updateActiveState
2346 if (_private && _private->page)
2347 _private->page->focusController()->setActive([[self window] isKeyWindow]);
2350 static PassOwnPtr<Vector<String> > toStringVector(NSArray* patterns)
2352 // Convert the patterns into Vectors.
2353 NSUInteger count = [patterns count];
2356 Vector<String>* patternsVector = new Vector<String>;
2357 for (NSUInteger i = 0; i < count; ++i) {
2358 id entry = [patterns objectAtIndex:i];
2359 if ([entry isKindOfClass:[NSString class]])
2360 patternsVector->append(String((NSString*)entry));
2362 return patternsVector;
2365 + (void)_addUserScriptToGroup:(NSString *)groupName world:(WebScriptWorld *)world source:(NSString *)source url:(NSURL *)url
2366 whitelist:(NSArray *)whitelist blacklist:(NSArray *)blacklist injectionTime:(WebUserScriptInjectionTime)injectionTime
2368 String group(groupName);
2369 if (group.isEmpty())
2372 PageGroup* pageGroup = PageGroup::pageGroup(group);
2376 pageGroup->addUserScriptToWorld(core(world), source, url, toStringVector(whitelist), toStringVector(blacklist),
2377 injectionTime == WebInjectAtDocumentStart ? InjectAtDocumentStart : InjectAtDocumentEnd);
2380 + (void)_addUserStyleSheetToGroup:(NSString *)groupName world:(WebScriptWorld *)world source:(NSString *)source url:(NSURL *)url
2381 whitelist:(NSArray *)whitelist blacklist:(NSArray *)blacklist
2383 String group(groupName);
2384 if (group.isEmpty())
2387 PageGroup* pageGroup = PageGroup::pageGroup(group);
2391 pageGroup->addUserStyleSheetToWorld(core(world), source, url, toStringVector(whitelist), toStringVector(blacklist));
2394 + (void)_removeUserScriptFromGroup:(NSString *)groupName world:(WebScriptWorld *)world url:(NSURL *)url
2396 String group(groupName);
2397 if (group.isEmpty())
2400 PageGroup* pageGroup = PageGroup::pageGroup(group);
2404 pageGroup->removeUserScriptFromWorld(core(world), url);
2407 + (void)_removeUserStyleSheetFromGroup:(NSString *)groupName world:(WebScriptWorld *)world url:(NSURL *)url
2409 String group(groupName);
2410 if (group.isEmpty())
2413 PageGroup* pageGroup = PageGroup::pageGroup(group);
2417 pageGroup->removeUserStyleSheetFromWorld(core(world), url);
2420 + (void)_removeUserScriptsFromGroup:(NSString *)groupName world:(WebScriptWorld *)world
2422 String group(groupName);
2423 if (group.isEmpty())
2426 PageGroup* pageGroup = PageGroup::pageGroup(group);
2430 pageGroup->removeUserScriptsFromWorld(core(world));
2433 + (void)_removeUserStyleSheetsFromGroup:(NSString *)groupName world:(WebScriptWorld *)world
2435 String group(groupName);
2436 if (group.isEmpty())
2439 PageGroup* pageGroup = PageGroup::pageGroup(group);
2443 pageGroup->removeUserStyleSheetsFromWorld(core(world));
2446 + (void)_removeAllUserContentFromGroup:(NSString *)groupName
2448 String group(groupName);
2449 if (group.isEmpty())
2452 PageGroup* pageGroup = PageGroup::pageGroup(group);
2456 pageGroup->removeAllUserContent();
2459 - (BOOL)cssAnimationsSuspended
2461 return _private->cssAnimationsSuspended;
2464 - (void)setCSSAnimationsSuspended:(BOOL)suspended
2466 if (suspended == _private->cssAnimationsSuspended)
2469 _private->cssAnimationsSuspended = suspended;
2471 Frame* frame = core([self mainFrame]);
2473 frame->animation()->suspendAnimations(frame->document());
2475 frame->animation()->resumeAnimations(frame->document());
2478 + (void)_setDomainRelaxationForbidden:(BOOL)forbidden forURLScheme:(NSString *)scheme
2480 SecurityOrigin::setDomainRelaxationForbiddenForURLScheme(forbidden, scheme);
2483 + (void)_registerURLSchemeAsSecure:(NSString *)scheme
2485 SecurityOrigin::registerURLSchemeAsSecure(scheme);
2490 @implementation _WebSafeForwarder
2492 // Used to send messages to delegates that implement informal protocols.
2494 - (id)initWithTarget:(id)t defaultTarget:(id)dt catchExceptions:(BOOL)c
2496 self = [super init];
2499 target = t; // Non retained.
2501 catchExceptions = c;
2505 - (void)forwardInvocation:(NSInvocation *)invocation
2507 if ([target respondsToSelector:[invocation selector]]) {
2508 if (catchExceptions) {
2510 [invocation invokeWithTarget:target];
2511 } @catch(id exception) {
2512 ReportDiscardedDelegateException([invocation selector], exception);
2515 [invocation invokeWithTarget:target];
2519 if ([defaultTarget respondsToSelector:[invocation selector]])
2520 [invocation invokeWithTarget:defaultTarget];
2522 // Do nothing quietly if method not implemented.
2525 - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
2527 return [defaultTarget methodSignatureForSelector:aSelector];
2532 @implementation WebView
2536 static BOOL initialized = NO;
2541 InitWebCoreSystemInterface();
2542 JSC::initializeThreading();
2543 WTF::initializeMainThreadToProcessMainThread();
2545 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_applicationWillTerminate) name:NSApplicationWillTerminateNotification object:NSApp];
2546 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:) name:WebPreferencesChangedNotification object:nil];
2547 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesRemovedNotification:) name:WebPreferencesRemovedNotification object:nil];
2549 continuousSpellCheckingEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebContinuousSpellCheckingEnabled];
2550 #ifndef BUILDING_ON_TIGER
2551 grammarCheckingEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebGrammarCheckingEnabled];
2554 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
2555 automaticQuoteSubstitutionEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticQuoteSubstitutionEnabled];
2556 automaticLinkDetectionEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticLinkDetectionEnabled];
2557 automaticDashSubstitutionEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticDashSubstitutionEnabled];
2558 automaticTextReplacementEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticTextReplacementEnabled];
2559 automaticSpellingCorrectionEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticSpellingCorrectionEnabled];
2563 + (void)_applicationWillTerminate
2565 applicationIsTerminating = YES;
2567 if (fastDocumentTeardownEnabled())
2568 [self closeAllWebViews];
2570 if (!pluginDatabaseClientCount)
2571 [WebPluginDatabase closeSharedDatabase];
2573 PageGroup::closeLocalStorage();
2576 + (BOOL)_canShowMIMEType:(NSString *)MIMEType allowingPlugins:(BOOL)allowPlugins
2578 return [self _viewClass:nil andRepresentationClass:nil forMIMEType:MIMEType allowingPlugins:allowPlugins];
2581 + (BOOL)canShowMIMEType:(NSString *)MIMEType
2583 return [self _canShowMIMEType:MIMEType allowingPlugins:YES];
2586 - (BOOL)_canShowMIMEType:(NSString *)MIMEType
2588 return [[self class] _canShowMIMEType:MIMEType allowingPlugins:[_private->preferences arePlugInsEnabled]];
2591 - (WebBasePluginPackage *)_pluginForMIMEType:(NSString *)MIMEType
2593 if (![_private->preferences arePlugInsEnabled])
2596 WebBasePluginPackage *pluginPackage = [[WebPluginDatabase sharedDatabase] pluginForMIMEType:MIMEType];
2598 return pluginPackage;
2600 if (_private->pluginDatabase)
2601 return [_private->pluginDatabase pluginForMIMEType:MIMEType];
2606 - (WebBasePluginPackage *)_pluginForExtension:(NSString *)extension
2608 if (![_private->preferences arePlugInsEnabled])
2611 WebBasePluginPackage *pluginPackage = [[WebPluginDatabase sharedDatabase] pluginForExtension:extension];
2613 return pluginPackage;
2615 if (_private->pluginDatabase)
2616 return [_private->pluginDatabase pluginForExtension:extension];
2621 - (void)addPluginInstanceView:(NSView *)view
2623 if (!_private->pluginDatabase)
2624 _private->pluginDatabase = [[WebPluginDatabase alloc] init];
2625 [_private->pluginDatabase addPluginInstanceView:view];
2628 - (void)removePluginInstanceView:(NSView *)view
2630 if (_private->pluginDatabase)
2631 [_private->pluginDatabase removePluginInstanceView:view];
2634 - (void)removePluginInstanceViewsFor:(WebFrame*)webFrame
2636 if (_private->pluginDatabase)
2637 [_private->pluginDatabase removePluginInstanceViewsFor:webFrame];
2640 - (BOOL)_isMIMETypeRegisteredAsPlugin:(NSString *)MIMEType
2642 if (![_private->preferences arePlugInsEnabled])
2645 if ([[WebPluginDatabase sharedDatabase] isMIMETypeRegistered:MIMEType])
2648 if (_private->pluginDatabase && [_private->pluginDatabase isMIMETypeRegistered:MIMEType])
2654 + (BOOL)canShowMIMETypeAsHTML:(NSString *)MIMEType
2656 return [WebFrameView _canShowMIMETypeAsHTML:MIMEType];
2659 + (NSArray *)MIMETypesShownAsHTML
2661 NSMutableDictionary *viewTypes = [WebFrameView _viewTypesAllowImageTypeOmission:YES];
2662 NSEnumerator *enumerator = [viewTypes keyEnumerator];
2664 NSMutableArray *array = [[[NSMutableArray alloc] init] autorelease];
2666 while ((key = [enumerator nextObject])) {
2667 if ([viewTypes objectForKey:key] == [WebHTMLView class])
2668 [array addObject:key];
2674 + (void)setMIMETypesShownAsHTML:(NSArray *)MIMETypes
2676 NSDictionary *viewTypes = [[WebFrameView _viewTypesAllowImageTypeOmission:YES] copy];
2677 NSEnumerator *enumerator = [viewTypes keyEnumerator];
2679 while ((key = [enumerator nextObject])) {
2680 if ([viewTypes objectForKey:key] == [WebHTMLView class])
2681 [WebView _unregisterViewClassAndRepresentationClassForMIMEType:key];
2684 int i, count = [MIMETypes count];
2685 for (i = 0; i < count; i++) {
2686 [WebView registerViewClass:[WebHTMLView class]
2687 representationClass:[WebHTMLRepresentation class]
2688 forMIMEType:[MIMETypes objectAtIndex:i]];
2690 [viewTypes release];
2693 + (NSURL *)URLFromPasteboard:(NSPasteboard *)pasteboard
2695 return [pasteboard _web_bestURL];
2698 + (NSString *)URLTitleFromPasteboard:(NSPasteboard *)pasteboard
2700 return [pasteboard stringForType:WebURLNamePboardType];
2703 + (void)registerURLSchemeAsLocal:(NSString *)protocol
2705 SecurityOrigin::registerURLSchemeAsLocal(protocol);
2708 - (id)_initWithArguments:(NSDictionary *) arguments
2710 NSCoder *decoder = [arguments objectForKey:@"decoder"];
2712 self = [self initWithCoder:decoder];
2714 ASSERT([arguments objectForKey:@"frame"]);
2715 NSValue *frameValue = [arguments objectForKey:@"frame"];
2716 NSRect frame = (frameValue ? [frameValue rectValue] : NSZeroRect);
2717 NSString *frameName = [arguments objectForKey:@"frameName"];
2718 NSString *groupName = [arguments objectForKey:@"groupName"];
2719 self = [self initWithFrame:frame frameName:frameName groupName:groupName];
2725 static bool clientNeedsWebViewInitThreadWorkaround()
2727 if (WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_WEBVIEW_INIT_THREAD_WORKAROUND))
2730 NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
2733 if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.installer"])
2737 if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.Automator"])
2740 // Automator Runner.
2741 if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.AutomatorRunner"])
2744 // Automator workflows.
2745 if ([bundleIdentifier _webkit_hasCaseInsensitivePrefix:@"com.apple.Automator."])
2748 #if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
2750 if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.Mail"])
2757 static bool needsWebViewInitThreadWorkaround()
2759 static bool isOldClient = clientNeedsWebViewInitThreadWorkaround();
2760 return isOldClient && !pthread_main_np();
2763 - (id)initWithFrame:(NSRect)f
2765 return [self initWithFrame:f frameName:nil groupName:nil];
2768 - (id)initWithFrame:(NSRect)f frameName:(NSString *)frameName groupName:(NSString *)groupName
2770 if (needsWebViewInitThreadWorkaround())
2771 return [[self _webkit_invokeOnMainThread] initWithFrame:f frameName:frameName groupName:groupName];
2773 WebCoreThreadViolationCheckRoundTwo();
2774 return [self _initWithFrame:f frameName:frameName groupName:groupName usesDocumentViews:YES];
2777 - (id)initWithCoder:(NSCoder *)decoder
2779 if (needsWebViewInitThreadWorkaround())
2780 return [[self _webkit_invokeOnMainThread] initWithCoder:decoder];
2782 WebCoreThreadViolationCheckRoundTwo();
2783 WebView *result = nil;
2786 NSString *frameName;
2787 NSString *groupName;
2788 WebPreferences *preferences;
2789 BOOL useBackForwardList = NO;
2790 BOOL allowsUndo = YES;
2792 result = [super initWithCoder:decoder];
2793 result->_private = [[WebViewPrivate alloc] init];
2795 // We don't want any of the archived subviews. The subviews will always
2796 // be created in _commonInitializationFrameName:groupName:.
2797 [[result subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
2799 if ([decoder allowsKeyedCoding]) {
2800 frameName = [decoder decodeObjectForKey:@"FrameName"];
2801 groupName = [decoder decodeObjectForKey:@"GroupName"];
2802 preferences = [decoder decodeObjectForKey:@"Preferences"];
2803 useBackForwardList = [decoder decodeBoolForKey:@"UseBackForwardList"];
2804 if ([decoder containsValueForKey:@"AllowsUndo"])
2805 allowsUndo = [decoder decodeBoolForKey:@"AllowsUndo"];
2808 [decoder decodeValueOfObjCType:@encode(int) at:&version];
2809 frameName = [decoder decodeObject];
2810 groupName = [decoder decodeObject];
2811 preferences = [decoder decodeObject];
2813 [decoder decodeValuesOfObjCTypes:"c", &useBackForwardList];
2814 // The allowsUndo field is no longer written out in encodeWithCoder, but since there are
2815 // version 3 NIBs that have this field encoded, we still need to read it in.
2817 [decoder decodeValuesOfObjCTypes:"c", &allowsUndo];
2820 if (![frameName isKindOfClass:[NSString class]])
2822 if (![groupName isKindOfClass:[NSString class]])
2824 if (![preferences isKindOfClass:[WebPreferences class]])
2827 LOG(Encoding, "FrameName = %@, GroupName = %@, useBackForwardList = %d\n", frameName, groupName, (int)useBackForwardList);
2828 [result _commonInitializationWithFrameName:frameName groupName:groupName usesDocumentViews:YES];
2829 [result page]->backForwardList()->setEnabled(useBackForwardList);
2830 result->_private->allowsUndo = allowsUndo;
2832 [result setPreferences:preferences];
2833 } @catch (NSException *localException) {
2841 - (void)encodeWithCoder:(NSCoder *)encoder
2843 // Set asside the subviews before we archive. We don't want to archive any subviews.
2844 // The subviews will always be created in _commonInitializationFrameName:groupName:.
2845 id originalSubviews = _subviews;
2848 [super encodeWithCoder:encoder];
2850 // Restore the subviews we set aside.
2851 _subviews = originalSubviews;
2853 BOOL useBackForwardList = _private->page && _private->page->backForwardList()->enabled();
2854 if ([encoder allowsKeyedCoding]) {
2855 [encoder encodeObject:[[self mainFrame] name] forKey:@"FrameName"];
2856 [encoder encodeObject:[self groupName] forKey:@"GroupName"];
2857 [encoder encodeObject:[self preferences] forKey:@"Preferences"];
2858 [encoder encodeBool:useBackForwardList forKey:@"UseBackForwardList"];
2859 [encoder encodeBool:_private->allowsUndo forKey:@"AllowsUndo"];
2861 int version = WebViewVersion;
2862 [encoder encodeValueOfObjCType:@encode(int) at:&version];
2863 [encoder encodeObject:[[self mainFrame] name]];
2864 [encoder encodeObject:[self groupName]];
2865 [encoder encodeObject:[self preferences]];
2866 [encoder encodeValuesOfObjCTypes:"c", &useBackForwardList];
2867 // DO NOT encode any new fields here, doing so will break older WebKit releases.
2870 LOG(Encoding, "FrameName = %@, GroupName = %@, useBackForwardList = %d\n", [[self mainFrame] name], [self groupName], (int)useBackForwardList);
2875 if (WebCoreObjCScheduleDeallocateOnMainThread([WebView class], self))
2878 // call close to ensure we tear-down completely
2879 // this maintains our old behavior for existing applications
2882 if ([[self class] shouldIncludeInWebKitStatistics])
2885 if ([self _needsFrameLoadDelegateRetainQuirk])
2886 [_private->frameLoadDelegate release];
2889 // [super dealloc] can end up dispatching against _private (3466082)
2897 ASSERT(_private->closed);
2906 // _close existed first, and some clients might be calling or overriding it, so call through.
2910 - (void)setShouldCloseWithWindow:(BOOL)close
2912 _private->shouldCloseWithWindow = close;
2915 - (BOOL)shouldCloseWithWindow
2917 return _private->shouldCloseWithWindow;
2920 - (void)addWindowObserversForWindow:(NSWindow *)window
2923 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowDidBecomeKey:)
2924 name:NSWindowDidBecomeKeyNotification object:nil];
2925 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowDidResignKey:)
2926 name:NSWindowDidResignKeyNotification object:nil];
2927 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillOrderOnScreen:)
2928 name:WKWindowWillOrderOnScreenNotification() object:window];
2932 - (void)removeWindowObservers
2934 NSWindow *window = [self window];
2936 [[NSNotificationCenter defaultCenter] removeObserver:self
2937 name:NSWindowDidBecomeKeyNotification object:nil];
2938 [[NSNotificationCenter defaultCenter] removeObserver:self
2939 name:NSWindowDidResignKeyNotification object:nil];
2940 [[NSNotificationCenter defaultCenter] removeObserver:self
2941 name:WKWindowWillOrderOnScreenNotification() object:window];
2945 - (void)viewWillMoveToWindow:(NSWindow *)window
2947 // Don't do anything if the WebView isn't initialized.
2948 // This happens when decoding a WebView in a nib.
2949 // FIXME: What sets up the observer of NSWindowWillCloseNotification in this case?
2950 if (!_private || _private->closed)
2953 if ([self window] && [self window] != [self hostWindow])
2954 [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowWillCloseNotification object:[self window]];
2957 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillClose:) name:NSWindowWillCloseNotification object:window];
2959 // Ensure that we will receive the events that WebHTMLView (at least) needs.
2960 // The following are expensive enough that we don't want to call them over
2961 // and over, so do them when we move into a window.
2962 [window setAcceptsMouseMovedEvents:YES];
2963 WKSetNSWindowShouldPostEventNotifications(window, YES);
2965 _private->page->setCanStartMedia(false);
2966 _private->page->willMoveOffscreen();
2969 if (window != [self window]) {
2970 [self removeWindowObservers];
2971 [self addWindowObserversForWindow:window];
2975 - (void)viewDidMoveToWindow
2977 // Don't do anything if we aren't initialized. This happens
2978 // when decoding a WebView. When WebViews are decoded their subviews
2979 // are created by initWithCoder: and so won't be normally
2980 // initialized. The stub views are discarded by WebView.
2981 if (!_private || _private->closed)
2984 if ([self window]) {
2985 _private->page->setCanStartMedia(true);
2986 _private->page->didMoveOnscreen();
2989 [self _updateActiveState];
2992 - (void)_windowDidBecomeKey:(NSNotification *)notification
2994 NSWindow *keyWindow = [notification object];
2995 if (keyWindow == [self window] || keyWindow == [[self window] attachedSheet])
2996 [self _updateActiveState];
2999 - (void)_windowDidResignKey:(NSNotification *)notification
3001 NSWindow *formerKeyWindow = [notification object];
3002 if (formerKeyWindow == [self window] || formerKeyWindow == [[self window] attachedSheet])
3003 [self _updateActiveState];
3006 - (void)_windowWillOrderOnScreen:(NSNotification *)notification
3008 if (![self shouldUpdateWhileOffscreen])
3009 [self setNeedsDisplay:YES];
3012 - (void)_windowWillClose:(NSNotification *)notification
3014 if ([self shouldCloseWithWindow] && ([self window] == [self hostWindow] || ([self window] && ![self hostWindow]) || (![self window] && [self hostWindow])))
3018 - (void)setPreferences:(WebPreferences *)prefs
3021 prefs = [WebPreferences standardPreferences];
3023 if (_private->preferences == prefs)
3026 [prefs willAddToWebView];
3028 WebPreferences *oldPrefs = _private->preferences;
3030 [[NSNotificationCenter defaultCenter] removeObserver:self name:WebPreferencesChangedNotification object:[self preferences]];
3031 [WebPreferences _removeReferenceForIdentifier:[oldPrefs identifier]];
3033 _private->preferences = [prefs retain];
3035 // After registering for the notification, post it so the WebCore settings update.
3036 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:)
3037 name:WebPreferencesChangedNotification object:[self preferences]];
3038 [[self preferences] _postPreferencesChangesNotification];
3040 [oldPrefs didRemoveFromWebView];
3044 - (WebPreferences *)preferences
3046 return _private->preferences;
3049 - (void)setPreferencesIdentifier:(NSString *)anIdentifier
3051 if (!_private->closed && ![anIdentifier isEqual:[[self preferences] identifier]]) {
3052 WebPreferences *prefs = [[WebPreferences alloc] initWithIdentifier:anIdentifier];
3053 [self setPreferences:prefs];
3058 - (NSString *)preferencesIdentifier
3060 return [[self preferences] identifier];
3064 - (void)setUIDelegate:delegate
3066 _private->UIDelegate = delegate;
3067 [_private->UIDelegateForwarder release];
3068 _private->UIDelegateForwarder = nil;
3073 return _private->UIDelegate;
3076 - (void)setResourceLoadDelegate: delegate
3078 _private->resourceProgressDelegate = delegate;
3079 [self _cacheResourceLoadDelegateImplementations];
3082 - resourceLoadDelegate
3084 return _private->resourceProgressDelegate;
3087 - (void)setDownloadDelegate: delegate
3089 _private->downloadDelegate = delegate;
3095 return _private->downloadDelegate;
3098 - (void)setPolicyDelegate:delegate
3100 _private->policyDelegate = delegate;
3101 [_private->policyDelegateForwarder release];
3102 _private->policyDelegateForwarder = nil;
3107 return _private->policyDelegate;
3110 - (void)setFrameLoadDelegate:delegate
3112 // <rdar://problem/6950660> - Due to some subtle WebKit changes - presumably to delegate callback behavior - we've
3113 // unconvered a latent bug in at least one WebKit app where the delegate wasn't properly retained by the app and
3114 // was dealloc'ed before being cleared.
3115 // This is an effort to keep such apps working for now.
3116 if ([self _needsFrameLoadDelegateRetainQuirk]) {
3118 [_private->frameLoadDelegate release];
3121 _private->frameLoadDelegate = delegate;
3122 [self _cacheFrameLoadDelegateImplementations];
3124 #if ENABLE(ICONDATABASE)
3125 // If this delegate wants callbacks for icons, fire up the icon database.
3126 if (_private->frameLoadDelegateImplementations.didReceiveIconForFrameFunc)
3127 [WebIconDatabase sharedIconDatabase];
3133 return _private->frameLoadDelegate;
3136 - (WebFrame *)mainFrame
3138 // This can be called in initialization, before _private has been set up (3465613)
3139 if (!_private || !_private->page)
3141 return kit(_private->page->mainFrame());
3144 - (WebFrame *)selectedFrame
3146 if (_private->usesDocumentViews) {
3147 // If the first responder is a view in our tree, we get the frame containing the first responder.
3148 // This is faster than searching the frame hierarchy, and will give us a result even in the case
3149 // where the focused frame doesn't actually contain a selection.
3150 WebFrame *focusedFrame = [self _focusedFrame];
3152 return focusedFrame;
3155 // If the first responder is outside of our view tree, we search for a frame containing a selection.
3156 // There should be at most only one of these.
3157 return [[self mainFrame] _findFrameWithSelection];
3160 - (WebBackForwardList *)backForwardList
3162 if (!_private->page)
3164 if (!_private->page->backForwardList()->enabled())
3166 return kit(_private->page->backForwardList());
3169 - (void)setMaintainsBackForwardList:(BOOL)flag
3171 if (!_private->page)
3173 _private->page->backForwardList()->setEnabled(flag);
3178 if (!_private->page)
3181 return _private->page->goBack();
3186 if (!_private->page)
3189 return _private->page->goForward();
3192 - (BOOL)goToBackForwardItem:(WebHistoryItem *)item
3194 if (!_private->page)
3197 _private->page->goToItem(core(item), FrameLoadTypeIndexedBackForward);
3201 - (void)setTextSizeMultiplier:(float)m
3203 [self _setZoomMultiplier:m isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3206 - (float)textSizeMultiplier
3208 return [self _realZoomMultiplierIsTextOnly] ? _private->zoomMultiplier : 1.0f;
3211 - (void)_setZoomMultiplier:(float)multiplier isTextOnly:(BOOL)isTextOnly
3213 // NOTE: This has no visible effect when viewing a PDF (see <rdar://problem/4737380>)
3214 _private->zoomMultiplier = multiplier;
3216 ASSERT(_private->page);
3218 _private->page->settings()->setZoomMode(isTextOnly ? ZoomTextOnly : ZoomPage);
3220 // FIXME: It would be nice to rework this code so that _private->zoomMultiplier doesn't exist
3221 // and instead FrameView::zoomFactor is used.
3222 Frame* coreFrame = [self _mainCoreFrame];
3224 if (FrameView* view = coreFrame->view())
3225 view->setZoomFactor(multiplier, isTextOnly ? ZoomTextOnly : ZoomPage);
3229 - (float)_zoomMultiplier:(BOOL)isTextOnly
3231 if (isTextOnly != [self _realZoomMultiplierIsTextOnly])
3233 return _private->zoomMultiplier;
3236 - (float)_realZoomMultiplier
3238 return _private->zoomMultiplier;
3241 - (BOOL)_realZoomMultiplierIsTextOnly
3243 if (!_private->page)
3246 return _private->page->settings()->zoomMode() == ZoomTextOnly;
3249 #define MinimumZoomMultiplier 0.5f
3250 #define MaximumZoomMultiplier 3.0f
3251 #define ZoomMultiplierRatio 1.2f
3253 - (BOOL)_canZoomOut:(BOOL)isTextOnly
3255 id docView = [[[self mainFrame] frameView] documentView];
3256 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
3257 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
3258 return [zoomingDocView _canZoomOut];
3260 return [self _zoomMultiplier:isTextOnly] / ZoomMultiplierRatio > MinimumZoomMultiplier;
3264 - (BOOL)_canZoomIn:(BOOL)isTextOnly
3266 id docView = [[[self mainFrame] frameView] documentView];
3267 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
3268 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
3269 return [zoomingDocView _canZoomIn];
3271 return [self _zoomMultiplier:isTextOnly] * ZoomMultiplierRatio < MaximumZoomMultiplier;
3274 - (IBAction)_zoomOut:(id)sender isTextOnly:(BOOL)isTextOnly
3276 id docView = [[[self mainFrame] frameView] documentView];
3277 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
3278 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
3279 return [zoomingDocView _zoomOut:sender];
3281 float newScale = [self _zoomMultiplier:isTextOnly] / ZoomMultiplierRatio;
3282 if (newScale > MinimumZoomMultiplier)
3283 [self _setZoomMultiplier:newScale isTextOnly:isTextOnly];
3286 - (IBAction)_zoomIn:(id)sender isTextOnly:(BOOL)isTextOnly
3288 id docView = [[[self mainFrame] frameView] documentView];
3289 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
3290 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
3291 return [zoomingDocView _zoomIn:sender];
3293 float newScale = [self _zoomMultiplier:isTextOnly] * ZoomMultiplierRatio;
3294 if (newScale < MaximumZoomMultiplier)
3295 [self _setZoomMultiplier:newScale isTextOnly:isTextOnly];
3298 - (BOOL)_canResetZoom:(BOOL)isTextOnly
3300 id docView = [[[self mainFrame] frameView] documentView];
3301 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
3302 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
3303 return [zoomingDocView _canResetZoom];
3305 return [self _zoomMultiplier:isTextOnly] != 1.0f;
3308 - (IBAction)_resetZoom:(id)sender isTextOnly:(BOOL)isTextOnly
3310 id docView = [[[self mainFrame] frameView] documentView];
3311 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
3312 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
3313 return [zoomingDocView _resetZoom:sender];
3315 if ([self _zoomMultiplier:isTextOnly] != 1.0f)
3316 [self _setZoomMultiplier:1.0f isTextOnly:isTextOnly];
3319 - (void)setApplicationNameForUserAgent:(NSString *)applicationName
3321 NSString *name = [applicationName copy];
3322 [_private->applicationNameForUserAgent release];
3323 _private->applicationNameForUserAgent = name;
3324 if (!_private->userAgentOverridden)
3325 _private->userAgent = String();
3328 - (NSString *)applicationNameForUserAgent
3330 return [[_private->applicationNameForUserAgent retain] autorelease];
3333 - (void)setCustomUserAgent:(NSString *)userAgentString
3335 _private->userAgent = userAgentString;
3336 _private->userAgentOverridden = userAgentString != nil;
3339 - (NSString *)customUserAgent
3341 if (!_private->userAgentOverridden)
3343 return _private->userAgent;
3346 - (void)setMediaStyle:(NSString *)mediaStyle
3348 if (_private->mediaStyle != mediaStyle) {
3349 [_private->mediaStyle release];
3350 _private->mediaStyle = [mediaStyle copy];
3354 - (NSString *)mediaStyle
3356 return _private->mediaStyle;
3359 - (BOOL)supportsTextEncoding
3361 id documentView = [[[self mainFrame] frameView] documentView];
3362 return [documentView conformsToProtocol:@protocol(WebDocumentText)]
3363 && [documentView supportsTextEncoding];
3366 - (void)setCustomTextEncodingName:(NSString *)encoding
3368 NSString *oldEncoding = [self customTextEncodingName];
3369 if (encoding == oldEncoding || [encoding isEqualToString:oldEncoding])
3371 if (Frame* mainFrame = [self _mainCoreFrame])
3372 mainFrame->loader()->reloadWithOverrideEncoding(encoding);
3375 - (NSString *)_mainFrameOverrideEncoding
3377 WebDataSource *dataSource = [[self mainFrame] provisionalDataSource];
3378 if (dataSource == nil)
3379 dataSource = [[self mainFrame] _dataSource];
3380 if (dataSource == nil)
3382 return nsStringNilIfEmpty([dataSource _documentLoader]->overrideEncoding());
3385 - (NSString *)customTextEncodingName
3387 return [self _mainFrameOverrideEncoding];
3390 - (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script
3392 // Return statements are only valid in a function but some applications pass in scripts
3393 // prefixed with return (<rdar://problems/5103720&4616860>) since older WebKit versions
3394 // silently ignored the return. If the application is linked against an earlier version
3395 // of WebKit we will strip the return so the script wont fail.
3396 if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_JAVASCRIPT_RETURN_QUIRK)) {
3397 NSRange returnStringRange = [script rangeOfString:@"return "];
3398 if (returnStringRange.length && !returnStringRange.location)
3399 script = [script substringFromIndex:returnStringRange.location + returnStringRange.length];
3402 NSString *result = [[self mainFrame] _stringByEvaluatingJavaScriptFromString:script];
3403 // The only way stringByEvaluatingJavaScriptFromString can return nil is if the frame was removed by the script
3404 // Since there's no way to get rid of the main frame, result will never ever be nil here.
3410 - (WebScriptObject *)windowScriptObject
3412 Frame* coreFrame = [self _mainCoreFrame];
3415 return coreFrame->script()->windowScriptObject();
3418 // Get the appropriate user-agent string for a particular URL.
3419 - (NSString *)userAgentForURL:(NSURL *)url
3421 if (_private->useSiteSpecificSpoofing) {
3422 // No current site-specific spoofs.
3425 if (_private->userAgent.isNull())
3426 _private->userAgent = [[self class] _standardUserAgentWithApplicationName:_private->applicationNameForUserAgent];
3428 return _private->userAgent;
3431 - (void)setHostWindow:(NSWindow *)hostWindow
3433 if (_private->closed && hostWindow)
3435 if (hostWindow == _private->hostWindow)
3438 Frame* coreFrame = [self _mainCoreFrame];
3439 if (_private->usesDocumentViews) {
3440 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
3441 [[[kit(frame) frameView] documentView] viewWillMoveToHostWindow:hostWindow];
3443 if (_private->hostWindow && [self window] != _private->hostWindow)
3444 [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowWillCloseNotification object:_private->hostWindow];
3446 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillClose:) name:NSWindowWillCloseNotification object:hostWindow];
3447 [_private->hostWindow release];
3448 _private->hostWindow = [hostWindow retain];
3449 if (_private->usesDocumentViews) {
3450 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
3451 [[[kit(frame) frameView] documentView] viewDidMoveToHostWindow];
3455 - (NSWindow *)hostWindow
3457 // -[WebView hostWindow] can sometimes be called from the WebView's [super dealloc] method
3458 // so we check here to make sure it's not null.
3462 return _private->hostWindow;
3465 - (NSView <WebDocumentView> *)documentViewAtWindowPoint:(NSPoint)point
3467 return [[self _frameViewAtWindowPoint:point] documentView];
3470 - (NSDictionary *)_elementAtWindowPoint:(NSPoint)windowPoint
3472 WebFrameView *frameView = [self _frameViewAtWindowPoint:windowPoint];
3475 NSView <WebDocumentView> *documentView = [frameView documentView];
3476 if ([documentView conformsToProtocol:@protocol(WebDocumentElement)]) {
3477 NSPoint point = [documentView convertPoint:windowPoint fromView:nil];
3478 return [(NSView <WebDocumentElement> *)documentView elementAtPoint:point];
3480 return [NSDictionary dictionaryWithObject:[frameView webFrame] forKey:WebElementFrameKey];
3483 - (NSDictionary *)elementAtPoint:(NSPoint)point
3485 return [self _elementAtWindowPoint:[self convertPoint:point toView:nil]];
3488 // The following 2 internal NSView methods are called on the drag destination to make scrolling while dragging work.
3489 // Scrolling while dragging will only work if the drag destination is in a scroll view. The WebView is the drag destination.
3490 // When dragging to a WebView, the document subview should scroll, but it doesn't because it is not the drag destination.
3491 // Forward these calls to the document subview to make its scroll view scroll.
3492 - (void)_autoscrollForDraggingInfo:(id)draggingInfo timeDelta:(NSTimeInterval)repeatDelta
3494 NSView <WebDocumentView> *documentView = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3495 [documentView _autoscrollForDraggingInfo:draggingInfo timeDelta:repeatDelta];
3498 - (BOOL)_shouldAutoscrollForDraggingInfo:(id)draggingInfo
3500 NSView <WebDocumentView> *documentView = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3501 return [documentView _shouldAutoscrollForDraggingInfo:draggingInfo];
3504 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)draggingInfo
3506 NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3507 WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]] ? (WebHTMLView*)view : nil);
3508 IntPoint client([draggingInfo draggingLocation]);
3509 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
3510 DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
3511 return core(self)->dragController()->dragEntered(&dragData);
3514 - (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)draggingInfo
3516 Page* page = core(self);
3518 return NSDragOperationNone;
3520 NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3521 WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]] ? (WebHTMLView*)view : nil);
3522 IntPoint client([draggingInfo draggingLocation]);
3523 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
3524 DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
3525 return page->dragController()->dragUpdated(&dragData);
3528 - (void)draggingExited:(id <NSDraggingInfo>)draggingInfo
3530 Page* page = core(self);
3534 NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3535 WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]] ? (WebHTMLView*)view : nil);
3536 IntPoint client([draggingInfo draggingLocation]);
3537 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
3538 DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
3539 page->dragController()->dragExited(&dragData);
3542 - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)draggingInfo
3547 - (BOOL)performDragOperation:(id <NSDraggingInfo>)draggingInfo
3549 NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3550 WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]]? (WebHTMLView*)view : nil);
3551 IntPoint client([draggingInfo draggingLocation]);
3552 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
3553 DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
3554 return core(self)->dragController()->performDrag(&dragData);
3557 - (NSView *)_hitTest:(NSPoint *)point dragTypes:(NSSet *)types
3559 NSView *hitView = [super _hitTest:point dragTypes:types];
3560 if (!hitView && [[self superview] mouse:*point inRect:[self frame]])
3565 - (BOOL)acceptsFirstResponder
3567 if (_private->usesDocumentViews)
3568 return [[[self mainFrame] frameView] acceptsFirstResponder];
3570 // FIXME (Viewless): Need more code from WebHTMLView here.
3574 - (BOOL)becomeFirstResponder
3576 if (_private->usesDocumentViews) {
3577 if (_private->becomingFirstResponder) {
3578 // Fix for unrepro infinite recursion reported in Radar 4448181. If we hit this assert on
3579 // a debug build, we should figure out what causes the problem and do a better fix.
3580 ASSERT_NOT_REACHED();
3584 // This works together with setNextKeyView to splice the WebView into
3585 // the key loop similar to the way NSScrollView does this. Note that
3586 // WebFrameView has very similar code.
3587 NSWindow *window = [self window];
3588 WebFrameView *mainFrameView = [[self mainFrame] frameView];
3590 NSResponder *previousFirstResponder = [[self window] _oldFirstResponderBeforeBecoming];
3591 BOOL fromOutside = ![previousFirstResponder isKindOfClass:[NSView class]] || (![(NSView *)previousFirstResponder isDescendantOf:self] && previousFirstResponder != self);
3593 if ([window keyViewSelectionDirection] == NSSelectingPrevious) {
3594 NSView *previousValidKeyView = [self previousValidKeyView];
3595 if (previousValidKeyView != self && previousValidKeyView != mainFrameView) {
3596 _private->becomingFirstResponder = YES;
3597 _private->becomingFirstResponderFromOutside = fromOutside;
3598 [window makeFirstResponder:previousValidKeyView];
3599 _private->becomingFirstResponderFromOutside = NO;
3600 _private->becomingFirstResponder = NO;
3606 if ([mainFrameView acceptsFirstResponder]) {
3607 _private->becomingFirstResponder = YES;
3608 _private->becomingFirstResponderFromOutside = fromOutside;
3609 [window makeFirstResponder:mainFrameView];
3610 _private->becomingFirstResponderFromOutside = NO;
3611 _private->becomingFirstResponder = NO;
3618 // FIXME (Viewless): Need more code from WebHTMLView here.
3622 - (NSView *)_webcore_effectiveFirstResponder
3624 if (_private && _private->usesDocumentViews) {
3625 if (WebFrameView *frameView = [[self mainFrame] frameView])
3626 return [frameView _webcore_effectiveFirstResponder];
3628 return [super _webcore_effectiveFirstResponder];
3631 - (void)setNextKeyView:(NSView *)view
3633 if (_private && _private->usesDocumentViews) {
3634 // This works together with becomeFirstResponder to splice the WebView into
3635 // the key loop similar to the way NSScrollView does this. Note that
3636 // WebFrameView has similar code.
3637 if (WebFrameView *mainFrameView = [[self mainFrame] frameView]) {
3638 [mainFrameView setNextKeyView:view];
3643 [super setNextKeyView:view];
3646 static WebFrame *incrementFrame(WebFrame *frame, BOOL forward, BOOL wrapFlag)
3648 Frame* coreFrame = core(frame);
3650 ? coreFrame->tree()->traverseNextWithWrap(wrapFlag)
3651 : coreFrame->tree()->traversePreviousWithWrap(wrapFlag));
3654 - (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag
3656 return [self searchFor:string direction:forward caseSensitive:caseFlag wrap:wrapFlag startInSelection:NO];
3659 + (void)registerViewClass:(Class)viewClass representationClass:(Class)representationClass forMIMEType:(NSString *)MIMEType
3661 [[WebFrameView _viewTypesAllowImageTypeOmission:YES] setObject:viewClass forKey:MIMEType];
3662 [[WebDataSource _repTypesAllowImageTypeOmission:YES] setObject:representationClass forKey:MIMEType];
3664 // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
3665 // in the WebCore MIMEType registry. For now we're doing this in a safe, limited manner
3666 // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
3667 if ([viewClass class] == [WebHTMLView class])
3668 MIMETypeRegistry::getSupportedNonImageMIMETypes().add(MIMEType);
3671 - (void)setGroupName:(NSString *)groupName
3673 if (!_private->page)
3675 _private->page->setGroupName(groupName);
3678 - (NSString *)groupName
3680 if (!_private->page)
3682 return _private->page->groupName();
3685 - (double)estimatedProgress
3687 if (!_private->page)
3689 return _private->page->progress()->estimatedProgress();
3692 - (NSArray *)pasteboardTypesForSelection
3694 NSView <WebDocumentView> *documentView = [[[self _selectedOrMainFrame] frameView] documentView];
3695 if ([documentView conformsToProtocol:@protocol(WebDocumentSelection)]) {
3696 return [(NSView <WebDocumentSelection> *)documentView pasteboardTypesForSelection];
3698 return [NSArray array];
3701 - (void)writeSelectionWithPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
3703 WebFrame *frame = [self _selectedOrMainFrame];
3704 if (frame && [frame _hasSelection]) {
3705 NSView <WebDocumentView> *documentView = [[frame frameView] documentView];
3706 if ([documentView conformsToProtocol:@protocol(WebDocumentSelection)])
3707 [(NSView <WebDocumentSelection> *)documentView writeSelectionWithPasteboardTypes:types toPasteboard:pasteboard];
3711 - (NSArray *)pasteboardTypesForElement:(NSDictionary *)element
3713 if ([element objectForKey:WebElementImageURLKey] != nil) {
3714 return [NSPasteboard _web_writableTypesForImageIncludingArchive:([element objectForKey:WebElementDOMNodeKey] != nil)];
3715 } else if ([element objectForKey:WebElementLinkURLKey] != nil) {
3716 return [NSPasteboard _web_writableTypesForURL];
3717 } else if ([[element objectForKey:WebElementIsSelectedKey] boolValue]) {
3718 return [self pasteboardTypesForSelection];
3720 return [NSArray array];
3723 - (void)writeElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
3725 if ([element objectForKey:WebElementImageURLKey] != nil) {
3726 [self _writeImageForElement:element withPasteboardTypes:types toPasteboard:pasteboard];
3727 } else if ([element objectForKey:WebElementLinkURLKey] != nil) {
3728 [self _writeLinkElement:element withPasteboardTypes:types toPasteboard:pasteboard];
3729 } else if ([[element objectForKey:WebElementIsSelectedKey] boolValue]) {
3730 [self writeSelectionWithPasteboardTypes:types toPasteboard:pasteboard];
3734 - (void)moveDragCaretToPoint:(NSPoint)point
3736 if (Page* page = core(self))
3737 page->dragController()->placeDragCaret(IntPoint([self convertPoint:point toView:nil]));
3740 - (void)removeDragCaret
3742 if (Page* page = core(self))
3743 page->dragController()->dragEnded();
3746 - (void)setMainFrameURL:(NSString *)URLString
3748 [[self mainFrame] loadRequest: [NSURLRequest requestWithURL: [NSURL _web_URLWithDataAsString: URLString]]];
3751 - (NSString *)mainFrameURL
3754 ds = [[self mainFrame] provisionalDataSource];
3756 ds = [[self mainFrame] _dataSource];
3757 return [[[ds request] URL] _web_originalDataAsString];
3762 LOG (Bindings, "isLoading = %d", (int)[self _isLoading]);
3763 return [self _isLoading];
3766 - (NSString *)mainFrameTitle
3768 NSString *mainFrameTitle = [[[self mainFrame] _dataSource] pageTitle];
3769 return (mainFrameTitle != nil) ? mainFrameTitle : (NSString *)@"";
3772 - (NSImage *)mainFrameIcon
3774 return [[WebIconDatabase sharedIconDatabase] iconForURL:[[[[self mainFrame] _dataSource] _URL] _web_originalDataAsString] withSize:WebIconSmallSize];
3777 - (DOMDocument *)mainFrameDocument
3779 // only return the actual value if the state we're in gives NSTreeController
3780 // enough time to release its observers on the old model
3781 if (_private->mainFrameDocumentReady)
3782 return [[self mainFrame] DOMDocument];
3786 - (void)setDrawsBackground:(BOOL)drawsBackground
3788 if (_private->drawsBackground == drawsBackground)
3790 _private->drawsBackground = drawsBackground;
3791 [[self mainFrame] _updateBackgroundAndUpdatesWhileOffscreen];
3794 - (BOOL)drawsBackground
3796 // This method can be called beneath -[NSView dealloc] after we have cleared _private,
3797 // indirectly via -[WebFrameView viewDidMoveToWindow].
3798 return !_private || _private->drawsBackground;
3801 - (void)setShouldUpdateWhileOffscreen:(BOOL)updateWhileOffscreen
3803 if (_private->shouldUpdateWhileOffscreen == updateWhileOffscreen)
3805 _private->shouldUpdateWhileOffscreen = updateWhileOffscreen;
3806 [[self mainFrame] _updateBackgroundAndUpdatesWhileOffscreen];
3809 - (BOOL)shouldUpdateWhileOffscreen
3811 return _private->shouldUpdateWhileOffscreen;
3814 - (void)setCurrentNodeHighlight:(WebNodeHighlight *)nodeHighlight
3816 id old = _private->currentNodeHighlight;
3817 _private->currentNodeHighlight = [nodeHighlight retain];
3821 - (WebNodeHighlight *)currentNodeHighlight
3823 return _private->currentNodeHighlight;
3826 - (NSView *)previousValidKeyView
3828 NSView *result = [super previousValidKeyView];
3830 // Work around AppKit bug 6905484. If the result is a view that's inside this one, it's
3831 // possible it is the wrong answer, because the fact that it's a descendant causes the
3832 // code that implements key view redirection to fail; this means we won't redirect to
3833 // the toolbar, for example, when we hit the edge of a window. Since the bug is specific
3834 // to cases where the receiver of previousValidKeyView is an ancestor of the last valid
3835 // key view in the loop, we can sidestep it by walking along previous key views until
3836 // we find one that is not a superview, then using that to call previousValidKeyView.
3838 if (![result isDescendantOf:self])
3841 // Use a visited set so we don't loop indefinitely when walking crazy key loops.
3842 // AppKit uses such sets internally and we want our loop to be as robust as its loops.
3843 RetainPtr<CFMutableSetRef> visitedViews = CFSetCreateMutable(0, 0, 0);
3844 CFSetAddValue(visitedViews.get(), result);
3846 NSView *previousView = self;
3848 CFSetAddValue(visitedViews.get(), previousView);
3849 previousView = [previousView previousKeyView];
3850 if (!previousView || CFSetGetValue(visitedViews.get(), previousView))
3852 } while ([result isDescendantOf:previousView]);
3853 return [previousView previousValidKeyView];
3858 @implementation WebView (WebIBActions)
3860 - (IBAction)takeStringURLFrom: sender
3862 NSString *URLString = [sender stringValue];
3864 [[self mainFrame] loadRequest: [NSURLRequest requestWithURL: [NSURL _web_URLWithDataAsString: URLString]]];
3869 if (!_private->page)
3872 return !!_private->page->backForwardList()->backItem();
3875 - (BOOL)canGoForward
3877 if (!_private->page)
3880 return !!_private->page->backForwardList()->forwardItem();
3883 - (IBAction)goBack:(id)sender
3888 - (IBAction)goForward:(id)sender
3893 - (IBAction)stopLoading:(id)sender
3895 [[self mainFrame] stopLoading];
3898 - (IBAction)reload:(id)sender
3900 [[self mainFrame] reload];
3903 - (IBAction)reloadFromOrigin:(id)sender
3905 [[self mainFrame] reloadFromOrigin];
3908 // FIXME: This code should move into WebCore so that it is not duplicated in each WebKit.
3909 // (This includes canMakeTextSmaller/Larger, makeTextSmaller/Larger, and canMakeTextStandardSize/makeTextStandardSize)
3910 - (BOOL)canMakeTextSmaller
3912 return [self _canZoomOut:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3915 - (IBAction)makeTextSmaller:(id)sender
3917 return [self _zoomOut:sender isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3920 - (BOOL)canMakeTextLarger
3922 return [self _canZoomIn:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3925 - (IBAction)makeTextLarger:(id)sender
3927 return [self _zoomIn:sender isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3930 - (BOOL)canMakeTextStandardSize
3932 return [self _canResetZoom:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3935 - (IBAction)makeTextStandardSize:(id)sender
3937 return [self _resetZoom:sender isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3940 - (IBAction)toggleSmartInsertDelete:(id)sender
3942 [self setSmartInsertDeleteEnabled:![self smartInsertDeleteEnabled]];
3945 - (IBAction)toggleContinuousSpellChecking:(id)sender
3947 [self setContinuousSpellCheckingEnabled:![self isContinuousSpellCheckingEnabled]];
3950 - (BOOL)_responderValidateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item
3952 id responder = [self _responderForResponderOperations];
3953 if (responder != self && [responder respondsToSelector:[item action]]) {
3954 if ([responder respondsToSelector:@selector(validateUserInterfaceItemWithoutDelegate:)])
3955 return [responder validateUserInterfaceItemWithoutDelegate:item];
3956 if ([responder respondsToSelector:@selector(validateUserInterfaceItem:)])
3957 return [responder validateUserInterfaceItem:item];
3963 #define VALIDATE(name) \
3964 else if (action == @selector(name:)) { return [self _responderValidateUserInterfaceItem:item]; }
3966 - (BOOL)validateUserInterfaceItemWithoutDelegate:(id <NSValidatedUserInterfaceItem>)item
3968 SEL action = [item action];
3970 if (action == @selector(goBack:)) {
3971 return [self canGoBack];
3972 } else if (action == @selector(goForward:)) {
3973 return [self canGoForward];
3974 } else if (action == @selector(makeTextLarger:)) {
3975 return [self canMakeTextLarger];
3976 } else if (action == @selector(makeTextSmaller:)) {
3977 return [self canMakeTextSmaller];
3978 } else if (action == @selector(makeTextStandardSize:)) {
3979 return [self canMakeTextStandardSize];
3980 } else if (action == @selector(reload:)) {
3981 return [[self mainFrame] _dataSource] != nil;
3982 } else if (action == @selector(stopLoading:)) {
3983 return [self _isLoading];
3984 } else if (action == @selector(toggleContinuousSpellChecking:)) {
3985 BOOL checkMark = NO;
3987 if ([self _continuousCheckingAllowed]) {
3988 checkMark = [self isContinuousSpellCheckingEnabled];
3991 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
3992 NSMenuItem *menuItem = (NSMenuItem *)item;
3993 [menuItem setState:checkMark ? NSOnState : NSOffState];
3996 } else if (action == @selector(toggleSmartInsertDelete:)) {
3997 BOOL checkMark = [self smartInsertDeleteEnabled];
3998 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
3999 NSMenuItem *menuItem = (NSMenuItem *)item;
4000 [menuItem setState:checkMark ? NSOnState : NSOffState];
4003 #ifndef BUILDING_ON_TIGER
4004 } else if (action == @selector(toggleGrammarChecking:)) {
4005 BOOL checkMark = [self isGrammarCheckingEnabled];
4006 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
4007 NSMenuItem *menuItem = (NSMenuItem *)item;
4008 [menuItem setState:checkMark ? NSOnState : NSOffState];
4012 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
4013 } else if (action == @selector(toggleAutomaticQuoteSubstitution:)) {
4014 BOOL checkMark = [self isAutomaticQuoteSubstitutionEnabled];
4015 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
4016 NSMenuItem *menuItem = (NSMenuItem *)item;
4017 [menuItem setState:checkMark ? NSOnState : NSOffState];
4020 } else if (action == @selector(toggleAutomaticLinkDetection:)) {
4021 BOOL checkMark = [self isAutomaticLinkDetectionEnabled];
4022 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
4023 NSMenuItem *menuItem = (NSMenuItem *)item;
4024 [menuItem setState:checkMark ? NSOnState : NSOffState];
4027 } else if (action == @selector(toggleAutomaticDashSubstitution:)) {
4028 BOOL checkMark = [self isAutomaticDashSubstitutionEnabled];
4029 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
4030 NSMenuItem *menuItem = (NSMenuItem *)item;
4031 [menuItem setState:checkMark ? NSOnState : NSOffState];
4034 } else if (action == @selector(toggleAutomaticTextReplacement:)) {
4035 BOOL checkMark = [self isAutomaticTextReplacementEnabled];
4036 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
4037 NSMenuItem *menuItem = (NSMenuItem *)item;
4038 [menuItem setState:checkMark ? NSOnState : NSOffState];
4041 } else if (action == @selector(toggleAutomaticSpellingCorrection:)) {
4042 BOOL checkMark = [self isAutomaticSpellingCorrectionEnabled];
4043 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
4044 NSMenuItem *menuItem = (NSMenuItem *)item;
4045 [menuItem setState:checkMark ? NSOnState : NSOffState];
4050 FOR_EACH_RESPONDER_SELECTOR(VALIDATE)
4055 - (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item
4057 BOOL result = [self validateUserInterfaceItemWithoutDelegate:item];
4058 return CallUIDelegateReturningBoolean(result, self, @selector(webView:validateUserInterfaceItem:defaultValidation:), item, result);
4063 @implementation WebView (WebPendingPublic)
4065 - (void)scheduleInRunLoop:(NSRunLoop *)runLoop forMode:(NSString *)mode
4067 if (runLoop && mode)
4068 core(self)->addSchedulePair(SchedulePair::create(runLoop, (CFStringRef)mode));
4071 - (void)unscheduleFromRunLoop:(NSRunLoop *)runLoop forMode:(NSString *)mode
4073 if (runLoop && mode)
4074 core(self)->removeSchedulePair(SchedulePair::create(runLoop, (CFStringRef)mode));
4077 - (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag startInSelection:(BOOL)startInSelection
4079 if (_private->closed)
4082 // Get the frame holding the selection, or start with the main frame
4083 WebFrame *startFrame = [self _selectedOrMainFrame];
4085 // Search the first frame, then all the other frames, in order
4086 NSView <WebDocumentSearching> *startSearchView = nil;
4087 WebFrame *frame = startFrame;
4089 WebFrame *nextFrame = incrementFrame(frame, forward, wrapFlag);
4091 BOOL onlyOneFrame = (frame == nextFrame);
4092 ASSERT(!onlyOneFrame || frame == startFrame);
4094 id <WebDocumentView> view = [[frame frameView] documentView];
4095 if ([view conformsToProtocol:@protocol(WebDocumentSearching)]) {
4096 NSView <WebDocumentSearching> *searchView = (NSView <WebDocumentSearching> *)view;
4098 if (frame == startFrame)
4099 startSearchView = searchView;
4102 // In some cases we have to search some content twice; see comment later in this method.
4103 // We can avoid ever doing this in the common one-frame case by passing YES for wrapFlag
4104 // here, and then bailing out before we get to the code that would search again in the
4106 BOOL wrapOnThisPass = wrapFlag && onlyOneFrame;
4107 if ([searchView conformsToProtocol:@protocol(WebDocumentIncrementalSearching)])
4108 foundString = [(NSView <WebDocumentIncrementalSearching> *)searchView searchFor:string direction:forward caseSensitive:caseFlag wrap:wrapOnThisPass startInSelection:startInSelection];
4110 foundString = [searchView searchFor:string direction:forward caseSensitive:caseFlag wrap:wrapOnThisPass];
4113 if (frame != startFrame)
4114 [startFrame _clearSelection];
4115 [[self window] makeFirstResponder:searchView];
4123 } while (frame && frame != startFrame);
4125 // 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
4126 // 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
4127 // 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
4128 // some content that we already searched on the first pass. In the worst case, we could search the entire contents of this frame twice.
4129 // To fix this, we'd need to add a mechanism to specify a range in which to search.
4130 if (wrapFlag && startSearchView) {
4132 if ([startSearchView conformsToProtocol:@protocol(WebDocumentIncrementalSearching)])
4133 foundString = [(NSView <WebDocumentIncrementalSearching> *)startSearchView searchFor:string direction:forward caseSensitive:caseFlag wrap:YES startInSelection:startInSelection];
4135 foundString = [startSearchView searchFor:string direction:forward caseSensitive:caseFlag wrap:YES];
4137 [[self window] makeFirstResponder:startSearchView];
4144 - (void)setHoverFeedbackSuspended:(BOOL)newValue
4146 if (_private->hoverFeedbackSuspended == newValue)
4149 _private->hoverFeedbackSuspended = newValue;
4151 if (_private->usesDocumentViews) {
4152 id <WebDocumentView> documentView = [[[self mainFrame] frameView] documentView];
4153 // FIXME: in a perfect world we'd do this in a general way that worked with any document view,
4154 // such as by calling a protocol method or using respondsToSelector or sending a notification.
4155 // But until there is any need for these more general solutions, we'll just hardwire it to work
4156 // with WebHTMLView.
4157 // Note that _hoverFeedbackSuspendedChanged needs to be called only on the main WebHTMLView, not
4158 // on each subframe separately.
4159 if ([documentView isKindOfClass:[WebHTMLView class]])
4160 [(WebHTMLView *)documentView _hoverFeedbackSuspendedChanged];
4164 [self _updateMouseoverWithFakeEvent];
4167 - (BOOL)isHoverFeedbackSuspended
4169 return _private->hoverFeedbackSuspended;
4172 - (void)setMainFrameDocumentReady:(BOOL)mainFrameDocumentReady
4174 // by setting this to NO, calls to mainFrameDocument are forced to return nil
4175 // setting this to YES lets it return the actual DOMDocument value
4176 // we use this to tell NSTreeController to reset its observers and clear its state
4177 if (_private->mainFrameDocumentReady == mainFrameDocumentReady)
4179 [self _willChangeValueForKey:_WebMainFrameDocumentKey];
4180 _private->mainFrameDocumentReady = mainFrameDocumentReady;
4181 [self _didChangeValueForKey:_WebMainFrameDocumentKey];
4182 // this will cause observers to call mainFrameDocument where this flag will be checked
4185 // This method name is used by Mail on Tiger (but not post-Tiger), so we shouldn't delete it
4186 // until the day comes when we're no longer supporting Mail on Tiger.
4187 - (WebFrame *)_frameForCurrentSelection
4189 return [self _selectedOrMainFrame];
4192 - (void)setTabKeyCyclesThroughElements:(BOOL)cyclesElements
4194 _private->tabKeyCyclesThroughElementsChanged = YES;
4196 _private->page->setTabKeyCyclesThroughElements(cyclesElements);
4199 - (BOOL)tabKeyCyclesThroughElements
4201 return _private->page && _private->page->tabKeyCyclesThroughElements();
4204 - (void)setScriptDebugDelegate:(id)delegate
4206 _private->scriptDebugDelegate = delegate;
4207 [self _cacheScriptDebugDelegateImplementations];
4210 [self _attachScriptDebuggerToAllFrames];
4212 [self _detachScriptDebuggerFromAllFrames];
4215 - (id)scriptDebugDelegate
4217 return _private->scriptDebugDelegate;
4220 - (void)setHistoryDelegate:(id)delegate
4222 _private->historyDelegate = delegate;
4223 [self _cacheHistoryDelegateImplementations];
4226 - (id)historyDelegate
4228 return _private->historyDelegate;
4233 Frame* coreFrame = [self _mainCoreFrame];
4236 return coreFrame->loader()->shouldClose();
4239 static NSAppleEventDescriptor* aeDescFromJSValue(ExecState* exec, JSValue jsValue)
4241 NSAppleEventDescriptor* aeDesc = 0;
4242 if (jsValue.isBoolean())
4243 return [NSAppleEventDescriptor descriptorWithBoolean:jsValue.getBoolean()];
4244 if (jsValue.isString())
4245 return [NSAppleEventDescriptor descriptorWithString:ustringToString(jsValue.getString(exec))];
4246 if (jsValue.isNumber()) {
4247 double value = jsValue.uncheckedGetNumber();
4248 int intValue = value;
4249 if (value == intValue)
4250 return [NSAppleEventDescriptor descriptorWithDescriptorType:typeSInt32 bytes:&intValue length:sizeof(intValue)];
4251 return [NSAppleEventDescriptor descriptorWithDescriptorType:typeIEEE64BitFloatingPoint bytes:&value length:sizeof(value)];
4253 if (jsValue.isObject()) {
4254 JSObject* object = jsValue.getObject();
4255 if (object->inherits(&DateInstance::info)) {
4256 DateInstance* date = static_cast<DateInstance*>(object);
4257 double ms = date->internalNumber();
4259 CFAbsoluteTime utcSeconds = ms / 1000 - kCFAbsoluteTimeIntervalSince1970;
4261 if (noErr == UCConvertCFAbsoluteTimeToLongDateTime(utcSeconds, &ldt))
4262 return [NSAppleEventDescriptor descriptorWithDescriptorType:typeLongDateTime bytes:&ldt length:sizeof(ldt)];
4265 else if (object->inherits(&JSArray::info)) {
4266 DEFINE_STATIC_LOCAL(HashSet<JSObject*>, visitedElems, ());
4267 if (!visitedElems.contains(object)) {
4268 visitedElems.add(object);
4270 JSArray* array = static_cast<JSArray*>(object);
4271 aeDesc = [NSAppleEventDescriptor listDescriptor];
4272 unsigned numItems = array->length();
4273 for (unsigned i = 0; i < numItems; ++i)
4274 [aeDesc insertDescriptor:aeDescFromJSValue(exec, array->get(exec, i)) atIndex:0];
4276 visitedElems.remove(object);
4280 JSValue primitive = object->toPrimitive(exec);
4281 if (exec->hadException()) {
4282 exec->clearException();
4283 return [NSAppleEventDescriptor nullDescriptor];
4285 return aeDescFromJSValue(exec, primitive);
4287 if (jsValue.isUndefined())
4288 return [NSAppleEventDescriptor descriptorWithTypeCode:cMissingValue];
4289 ASSERT(jsValue.isNull());
4290 return [NSAppleEventDescriptor nullDescriptor];
4293 - (NSAppleEventDescriptor *)aeDescByEvaluatingJavaScriptFromString:(NSString *)script
4295 Frame* coreFrame = [self _mainCoreFrame];
4298 if (!coreFrame->document())
4300 JSValue result = coreFrame->script()->executeScript(script, true).jsValue();
4301 if (!result) // FIXME: pass errors
4303 JSLock lock(SilenceAssertionsOnly);
4304 return aeDescFromJSValue(coreFrame->script()->globalObject(mainThreadNormalWorld())->globalExec(), result);
4307 - (BOOL)canMarkAllTextMatches
4309 WebFrame *frame = [self mainFrame];
4311 id <WebDocumentView> view = [[frame frameView] documentView];
4312 if (view && ![view conformsToProtocol:@protocol(WebMultipleTextMatches)])
4315 frame = incrementFrame(frame, YES, NO);
4321 - (NSUInteger)markAllMatchesForText:(NSString *)string caseSensitive:(BOOL)caseFlag highlight:(BOOL)highlight limit:(NSUInteger)limit
4323 WebFrame *frame = [self mainFrame];
4324 unsigned matchCount = 0;
4326 id <WebDocumentView> view = [[frame frameView] documentView];
4327 if ([view conformsToProtocol:@protocol(WebMultipleTextMatches)]) {
4328 [(NSView <WebMultipleTextMatches>*)view setMarkedTextMatchesAreHighlighted:highlight];
4330 ASSERT(limit == 0 || matchCount < limit);
4331 matchCount += [(NSView <WebMultipleTextMatches>*)view markAllMatchesForText:string caseSensitive:caseFlag limit:limit == 0 ? 0 : limit - matchCount];
4333 // Stop looking if we've reached the limit. A limit of 0 means no limit.
4334 if (limit > 0 && matchCount >= limit)
4338 frame = incrementFrame(frame, YES, NO);
4344 - (void)unmarkAllTextMatches
4346 WebFrame *frame = [self mainFrame];
4348 id <WebDocumentView> view = [[frame frameView] documentView];
4349 if ([view conformsToProtocol:@protocol(WebMultipleTextMatches)])
4350 [(NSView <WebMultipleTextMatches>*)view unmarkAllTextMatches];
4352 frame = incrementFrame(frame, YES, NO);
4356 - (NSArray *)rectsForTextMatches
4358 NSMutableArray *result = [NSMutableArray array];
4359 WebFrame *frame = [self mainFrame];
4361 id <WebDocumentView> view = [[frame frameView] documentView];
4362 if ([view conformsToProtocol:@protocol(WebMultipleTextMatches)]) {
4363 NSView <WebMultipleTextMatches> *documentView = (NSView <WebMultipleTextMatches> *)view;
4364 NSRect documentViewVisibleRect = [documentView visibleRect];
4365 NSArray *originalRects = [documentView rectsForTextMatches];
4366 unsigned rectCount = [originalRects count];
4368 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
4369 for (rectIndex = 0; rectIndex < rectCount; ++rectIndex) {
4370 NSRect r = [[originalRects objectAtIndex:rectIndex] rectValue];
4371 // Clip rect to document view's visible rect so rect is confined to subframe
4372 r = NSIntersectionRect(r, documentViewVisibleRect);
4373 if (NSIsEmptyRect(r))
4376 // Convert rect to our coordinate system
4377 r = [documentView convertRect:r toView:self];
4378 [result addObject:[NSValue valueWithRect:r]];
4379 if (rectIndex % 10 == 0) {
4381 pool = [[NSAutoreleasePool alloc] init];
4387 frame = incrementFrame(frame, YES, NO);
4393 - (void)scrollDOMRangeToVisible:(DOMRange *)range
4395 [[[[range startContainer] ownerDocument] webFrame] _scrollDOMRangeToVisible:range];
4400 return _private->allowsUndo;
4403 - (void)setAllowsUndo:(BOOL)flag
4405 _private->allowsUndo = flag;
4408 - (void)setPageSizeMultiplier:(float)m
4410 [self _setZoomMultiplier:m isTextOnly:NO];
4413 - (float)pageSizeMultiplier
4415 return ![self _realZoomMultiplierIsTextOnly] ? _private->zoomMultiplier : 1.0f;
4418 - (BOOL)canZoomPageIn
4420 return [self _canZoomIn:NO];
4423 - (IBAction)zoomPageIn:(id)sender
4425 return [self _zoomIn:sender isTextOnly:NO];
4428 - (BOOL)canZoomPageOut
4430 return [self _canZoomOut:NO];
4433 - (IBAction)zoomPageOut:(id)sender
4435 return [self _zoomOut:sender isTextOnly:NO];
4438 - (BOOL)canResetPageZoom
4440 return [self _canResetZoom:NO];
4443 - (IBAction)resetPageZoom:(id)sender
4445 return [self _resetZoom:sender isTextOnly:NO];
4448 - (void)setMediaVolume:(float)volume
4451 _private->page->setMediaVolume(volume);
4454 - (float)mediaVolume
4456 if (!_private->page)
4459 return _private->page->mediaVolume();
4462 - (void)addVisitedLinks:(NSArray *)visitedLinks
4464 PageGroup& group = core(self)->group();
4466 NSEnumerator *enumerator = [visitedLinks objectEnumerator];
4467 while (NSString *url = [enumerator nextObject]) {
4468 size_t length = [url length];
4469 const UChar* characters = CFStringGetCharactersPtr(reinterpret_cast<CFStringRef>(url));
4471 group.addVisitedLink(characters, length);
4473 Vector<UChar, 512> buffer(length);
4474 [url getCharacters:buffer.data()];
4475 group.addVisitedLink(buffer.data(), length);
4482 @implementation WebView (WebViewPrintingPrivate)
4484 - (float)_headerHeight
4486 return CallUIDelegateReturningFloat(self, @selector(webViewHeaderHeight:));
4489 - (float)_footerHeight
4491 return CallUIDelegateReturningFloat(self, @selector(webViewFooterHeight:));
4494 - (void)_drawHeaderInRect:(NSRect)rect
4496 #ifdef DEBUG_HEADER_AND_FOOTER
4497 NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
4498 [currentContext saveGraphicsState];
4499 [[NSColor yellowColor] set];
4501 [currentContext restoreGraphicsState];
4504 SEL selector = @selector(webView:drawHeaderInRect:);
4505 if (![_private->UIDelegate respondsToSelector:selector])
4508 NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
4509 [currentContext saveGraphicsState];
4512 CallUIDelegate(self, selector, rect);
4514 [currentContext restoreGraphicsState];
4517 - (void)_drawFooterInRect:(NSRect)rect
4519 #ifdef DEBUG_HEADER_AND_FOOTER
4520 NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
4521 [currentContext saveGraphicsState];
4522 [[NSColor cyanColor] set];
4524 [currentContext restoreGraphicsState];
4527 SEL selector = @selector(webView:drawFooterInRect:);
4528 if (![_private->UIDelegate respondsToSelector:selector])
4531 NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
4532 [currentContext saveGraphicsState];
4535 CallUIDelegate(self, selector, rect);
4537 [currentContext restoreGraphicsState];
4540 - (void)_adjustPrintingMarginsForHeaderAndFooter
4542 NSPrintOperation *op = [NSPrintOperation currentOperation];
4543 NSPrintInfo *info = [op printInfo];
4544 NSMutableDictionary *infoDictionary = [info dictionary];
4546 // We need to modify the top and bottom margins in the NSPrintInfo to account for the space needed by the
4547 // header and footer. Because this method can be called more than once on the same NSPrintInfo (see 5038087),
4548 // we stash away the unmodified top and bottom margins the first time this method is called, and we read from
4549 // those stashed-away values on subsequent calls.
4550 float originalTopMargin;
4551 float originalBottomMargin;
4552 NSNumber *originalTopMarginNumber = [infoDictionary objectForKey:WebKitOriginalTopPrintingMarginKey];
4553 if (!originalTopMarginNumber) {
4554 ASSERT(![infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey]);
4555 originalTopMargin = [info topMargin];
4556 originalBottomMargin = [info bottomMargin];
4557 [infoDictionary setObject:[NSNumber numberWithFloat:originalTopMargin] forKey:WebKitOriginalTopPrintingMarginKey];
4558 [infoDictionary setObject:[NSNumber numberWithFloat:originalBottomMargin] forKey:WebKitOriginalBottomPrintingMarginKey];
4560 ASSERT([originalTopMarginNumber isKindOfClass:[NSNumber class]]);
4561 ASSERT([[infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey] isKindOfClass:[NSNumber class]]);
4562 originalTopMargin = [originalTopMarginNumber floatValue];
4563 originalBottomMargin = [[infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey] floatValue];
4566 float scale = [op _web_pageSetupScaleFactor];
4567 [info setTopMargin:originalTopMargin + [self _headerHeight] * scale];
4568 [info setBottomMargin:originalBottomMargin + [self _footerHeight] * scale];
4571 - (void)_drawHeaderAndFooter
4573 // The header and footer rect height scales with the page, but the width is always
4574 // all the way across the printed page (inset by printing margins).
4575 NSPrintOperation *op = [NSPrintOperation currentOperation];
4576 float scale = [op _web_pageSetupScaleFactor];
4577 NSPrintInfo *printInfo = [op printInfo];
4578 NSSize paperSize = [printInfo paperSize];
4579 float headerFooterLeft = [printInfo leftMargin]/scale;
4580 float headerFooterWidth = (paperSize.width - ([printInfo leftMargin] + [printInfo rightMargin]))/scale;
4581 NSRect footerRect = NSMakeRect(headerFooterLeft, [printInfo bottomMargin]/scale - [self _footerHeight] ,
4582 headerFooterWidth, [self _footerHeight]);
4583 NSRect headerRect = NSMakeRect(headerFooterLeft, (paperSize.height - [printInfo topMargin])/scale,
4584 headerFooterWidth, [self _headerHeight]);
4586 [self _drawHeaderInRect:headerRect];
4587 [self _drawFooterInRect:footerRect];
4591 @implementation WebView (WebDebugBinding)
4593 - (void)addObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context
4595 LOG (Bindings, "addObserver:%p forKeyPath:%@ options:%x context:%p", anObserver, keyPath, options, context);
4596 [super addObserver:anObserver forKeyPath:keyPath options:options context:context];
4599 - (void)removeObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath
4601 LOG (Bindings, "removeObserver:%p forKeyPath:%@", anObserver, keyPath);
4602 [super removeObserver:anObserver forKeyPath:keyPath];
4607 //==========================================================================================
4610 @implementation WebView (WebViewCSS)
4612 - (DOMCSSStyleDeclaration *)computedStyleForElement:(DOMElement *)element pseudoElement:(NSString *)pseudoElement
4614 // FIXME: is this the best level for this conversion?
4615 if (pseudoElement == nil)
4616 pseudoElement = @"";
4618 return [[element ownerDocument] getComputedStyle:element pseudoElement:pseudoElement];
4623 @implementation WebView (WebViewEditing)
4625 - (DOMRange *)editableDOMRangeForPoint:(NSPoint)point
4627 Page* page = core(self);
4630 return kit(page->mainFrame()->editor()->rangeForPoint(IntPoint([self convertPoint:point toView:nil])).get());
4633 - (BOOL)_shouldChangeSelectedDOMRange:(DOMRange *)currentRange toDOMRange:(DOMRange *)proposedRange affinity:(NSSelectionAffinity)selectionAffinity stillSelecting:(BOOL)flag
4635 // 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
4636 if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_APERTURE_QUIRK) && [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.Aperture"])
4638 return [[self _editingDelegateForwarder] webView:self shouldChangeSelectedDOMRange:currentRange toDOMRange:proposedRange affinity:selectionAffinity stillSelecting:flag];
4641 - (BOOL)maintainsInactiveSelection
4646 - (void)setSelectedDOMRange:(DOMRange *)range affinity:(NSSelectionAffinity)selectionAffinity
4648 Frame* coreFrame = core([self _selectedOrMainFrame]);
4653 coreFrame->selection()->clear();
4655 // Derive the frame to use from the range passed in.
4656 // Using _selectedOrMainFrame could give us a different document than
4657 // the one the range uses.
4658 coreFrame = core([range startContainer])->document()->frame();
4662 coreFrame->selection()->setSelectedRange(core(range), core(selectionAffinity), true);
4666 - (DOMRange *)selectedDOMRange
4668 Frame* coreFrame = core([self _selectedOrMainFrame]);
4671 return kit(coreFrame->selection()->toNormalizedRange().get());
4674 - (NSSelectionAffinity)selectionAffinity
4676 Frame* coreFrame = core([self _selectedOrMainFrame]);
4678 return NSSelectionAffinityDownstream;
4679 return kit(coreFrame->selection()->affinity());
4682 - (void)setEditable:(BOOL)flag
4684 if (_private->editable != flag) {
4685 _private->editable = flag;
4686 if (!_private->tabKeyCyclesThroughElementsChanged && _private->page)
4687 _private->page->setTabKeyCyclesThroughElements(!flag);
4688 Frame* mainFrame = [self _mainCoreFrame];
4691 mainFrame->applyEditingStyleToBodyElement();
4692 // If the WebView is made editable and the selection is empty, set it to something.
4693 if (![self selectedDOMRange])
4694 mainFrame->setSelectionFromNone();
4702 return _private->editable;
4705 - (void)setTypingStyle:(DOMCSSStyleDeclaration *)style
4707 // We don't know enough at thls level to pass in a relevant WebUndoAction; we'd have to
4708 // change the API to allow this.
4709 [[self _selectedOrMainFrame] _setTypingStyle:style withUndoAction:EditActionUnspecified];
4712 - (DOMCSSStyleDeclaration *)typingStyle
4714 return [[self _selectedOrMainFrame] _typingStyle];
4717 - (void)setSmartInsertDeleteEnabled:(BOOL)flag
4719 if (_private->smartInsertDeleteEnabled != flag) {
4720 _private->smartInsertDeleteEnabled = flag;
4721 [[NSUserDefaults standardUserDefaults] setBool:_private->smartInsertDeleteEnabled forKey:WebSmartInsertDeleteEnabled];
4724 [self setSelectTrailingWhitespaceEnabled:false];
4727 - (BOOL)smartInsertDeleteEnabled
4729 return _private->smartInsertDeleteEnabled;
4732 - (void)setContinuousSpellCheckingEnabled:(BOOL)flag
4734 if (continuousSpellCheckingEnabled != flag) {
4735 continuousSpellCheckingEnabled = flag;
4736 [[NSUserDefaults standardUserDefaults] setBool:continuousSpellCheckingEnabled forKey:WebContinuousSpellCheckingEnabled];
4739 if ([self isContinuousSpellCheckingEnabled]) {
4740 [[self class] _preflightSpellChecker];
4742 [[self mainFrame] _unmarkAllMisspellings];
4746 - (BOOL)isContinuousSpellCheckingEnabled
4748 return (continuousSpellCheckingEnabled && [self _continuousCheckingAllowed]);
4751 - (NSInteger)spellCheckerDocumentTag
4753 if (!_private->hasSpellCheckerDocumentTag) {
4754 _private->spellCheckerDocumentTag = [NSSpellChecker uniqueSpellDocumentTag];
4755 _private->hasSpellCheckerDocumentTag = YES;
4757 return _private->spellCheckerDocumentTag;
4760 - (NSUndoManager *)undoManager
4762 if (!_private->allowsUndo)
4765 NSUndoManager *undoManager = [[self _editingDelegateForwarder] undoManagerForWebView:self];
4769 return [super undoManager];
4772 - (void)registerForEditingDelegateNotification:(NSString *)name selector:(SEL)selector
4774 NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
4775 if ([_private->editingDelegate respondsToSelector:selector])
4776 [defaultCenter addObserver:_private->editingDelegate selector:selector name:name object:self];
4779 - (void)setEditingDelegate:(id)delegate
4781 if (_private->editingDelegate == delegate)
4784 NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
4786 // remove notifications from current delegate
4787 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidBeginEditingNotification object:self];
4788 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidChangeNotification object:self];
4789 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidEndEditingNotification object:self];
4790 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidChangeTypingStyleNotification object:self];
4791 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidChangeSelectionNotification object:self];
4793 _private->editingDelegate = delegate;
4794 [_private->editingDelegateForwarder release];
4795 _private->editingDelegateForwarder = nil;
4797 // add notifications for new delegate
4798 [self registerForEditingDelegateNotification:WebViewDidBeginEditingNotification selector:@selector(webViewDidBeginEditing:)];
4799 [self registerForEditingDelegateNotification:WebViewDidChangeNotification selector:@selector(webViewDidChange:)];
4800 [self registerForEditingDelegateNotification:WebViewDidEndEditingNotification selector:@selector(webViewDidEndEditing:)];
4801 [self registerForEditingDelegateNotification:WebViewDidChangeTypingStyleNotification selector:@selector(webViewDidChangeTypingStyle:)];
4802 [self registerForEditingDelegateNotification:WebViewDidChangeSelectionNotification selector:@selector(webViewDidChangeSelection:)];
4805 - (id)editingDelegate
4807 return _private->editingDelegate;
4810 - (DOMCSSStyleDeclaration *)styleDeclarationWithText:(NSString *)text
4812 // FIXME: Should this really be attached to the document with the current selection?
4813 DOMCSSStyleDeclaration *decl = [[[self _selectedOrMainFrame] DOMDocument] createCSSStyleDeclaration];
4814 [decl setCssText:text];
4820 @implementation WebView (WebViewGrammarChecking)
4822 // FIXME: This method should be merged into WebViewEditing when we're not in API freeze
4823 - (BOOL)isGrammarCheckingEnabled
4825 #ifdef BUILDING_ON_TIGER
4828 return grammarCheckingEnabled;
4832 #ifndef BUILDING_ON_TIGER
4833 // FIXME: This method should be merged into WebViewEditing when we're not in API freeze
4834 - (void)setGrammarCheckingEnabled:(BOOL)flag
4836 if (grammarCheckingEnabled == flag)
4839 grammarCheckingEnabled = flag;
4840 [[NSUserDefaults standardUserDefaults] setBool:grammarCheckingEnabled forKey:WebGrammarCheckingEnabled];
4842 #ifndef BUILDING_ON_LEOPARD
4843 [[NSSpellChecker sharedSpellChecker] updatePanels];
4845 NSSpellChecker *spellChecker = [NSSpellChecker sharedSpellChecker];
4846 if ([spellChecker respondsToSelector:@selector(_updateGrammar)])
4847 [spellChecker performSelector:@selector(_updateGrammar)];
4850 // We call _preflightSpellChecker when turning continuous spell checking on, but we don't need to do that here
4851 // because grammar checking only occurs on code paths that already preflight spell checking appropriately.
4853 if (![self isGrammarCheckingEnabled])
4854 [[self mainFrame] _unmarkAllBadGrammar];
4857 // FIXME: This method should be merged into WebIBActions when we're not in API freeze
4858 - (void)toggleGrammarChecking:(id)sender
4860 [self setGrammarCheckingEnabled:![self isGrammarCheckingEnabled]];
4866 @implementation WebView (WebViewTextChecking)
4868 - (BOOL)isAutomaticQuoteSubstitutionEnabled
4870 #if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
4873 return automaticQuoteSubstitutionEnabled;
4877 - (BOOL)isAutomaticLinkDetectionEnabled
4879 #if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
4882 return automaticLinkDetectionEnabled;
4886 - (BOOL)isAutomaticDashSubstitutionEnabled
4888 #if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
4891 return automaticDashSubstitutionEnabled;
4895 - (BOOL)isAutomaticTextReplacementEnabled
4897 #if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
4900 return automaticTextReplacementEnabled;
4904 - (BOOL)isAutomaticSpellingCorrectionEnabled
4906 #if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
4909 return automaticSpellingCorrectionEnabled;
4913 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
4915 - (void)setAutomaticQuoteSubstitutionEnabled:(BOOL)flag
4917 if (automaticQuoteSubstitutionEnabled == flag)
4919 automaticQuoteSubstitutionEnabled = flag;
4920 [[NSUserDefaults standardUserDefaults] setBool:automaticQuoteSubstitutionEnabled forKey:WebAutomaticQuoteSubstitutionEnabled];
4921 [[NSSpellChecker sharedSpellChecker] updatePanels];
4924 - (void)toggleAutomaticQuoteSubstitution:(id)sender
4926 [self setAutomaticQuoteSubstitutionEnabled:![self isAutomaticQuoteSubstitutionEnabled]];
4929 - (void)setAutomaticLinkDetectionEnabled:(BOOL)flag
4931 if (automaticLinkDetectionEnabled == flag)
4933 automaticLinkDetectionEnabled = flag;
4934 [[NSUserDefaults standardUserDefaults] setBool:automaticLinkDetectionEnabled forKey:WebAutomaticLinkDetectionEnabled];
4935 [[NSSpellChecker sharedSpellChecker] updatePanels];
4938 - (void)toggleAutomaticLinkDetection:(id)sender
4940 [self setAutomaticLinkDetectionEnabled:![self isAutomaticLinkDetectionEnabled]];
4943 - (void)setAutomaticDashSubstitutionEnabled:(BOOL)flag
4945 if (automaticDashSubstitutionEnabled == flag)
4947 automaticDashSubstitutionEnabled = flag;
4948 [[NSUserDefaults standardUserDefaults] setBool:automaticDashSubstitutionEnabled forKey:WebAutomaticDashSubstitutionEnabled];
4949 [[NSSpellChecker sharedSpellChecker] updatePanels];
4952 - (void)toggleAutomaticDashSubstitution:(id)sender
4954 [self setAutomaticDashSubstitutionEnabled:![self isAutomaticDashSubstitutionEnabled]];
4957 - (void)setAutomaticTextReplacementEnabled:(BOOL)flag
4959 if (automaticTextReplacementEnabled == flag)
4961 automaticTextReplacementEnabled = flag;
4962 [[NSUserDefaults standardUserDefaults] setBool:automaticTextReplacementEnabled forKey:WebAutomaticTextReplacementEnabled];
4963 [[NSSpellChecker sharedSpellChecker] updatePanels];
4966 - (void)toggleAutomaticTextReplacement:(id)sender
4968 [self setAutomaticTextReplacementEnabled:![self isAutomaticTextReplacementEnabled]];
4971 - (void)setAutomaticSpellingCorrectionEnabled:(BOOL)flag
4973 if (automaticSpellingCorrectionEnabled == flag)
4975 automaticSpellingCorrectionEnabled = flag;
4976 [[NSUserDefaults standardUserDefaults] setBool:automaticSpellingCorrectionEnabled forKey:WebAutomaticSpellingCorrectionEnabled];
4977 [[NSSpellChecker sharedSpellChecker] updatePanels];
4980 - (void)toggleAutomaticSpellingCorrection:(id)sender
4982 [self setAutomaticSpellingCorrectionEnabled:![self isAutomaticSpellingCorrectionEnabled]];
4989 @implementation WebView (WebViewUndoableEditing)
4991 - (void)replaceSelectionWithNode:(DOMNode *)node
4993 [[self _selectedOrMainFrame] _replaceSelectionWithNode:node selectReplacement:YES smartReplace:NO matchStyle:NO];
4996 - (void)replaceSelectionWithText:(NSString *)text
4998 [[self _selectedOrMainFrame] _replaceSelectionWithText:text selectReplacement:YES smartReplace:NO];
5001 - (void)replaceSelectionWithMarkupString:(NSString *)markupString
5003 [[self _selectedOrMainFrame] _replaceSelectionWithMarkupString:markupString baseURLString:nil selectReplacement:YES smartReplace:NO];
5006 - (void)replaceSelectionWithArchive:(WebArchive *)archive
5008 [[[self _selectedOrMainFrame] _dataSource] _replaceSelectionWithArchive:archive selectReplacement:YES];
5011 - (void)deleteSelection
5013 WebFrame *webFrame = [self _selectedOrMainFrame];
5014 Frame* coreFrame = core(webFrame);
5016 coreFrame->editor()->deleteSelectionWithSmartDelete([(WebHTMLView *)[[webFrame frameView] documentView] _canSmartCopyOrDelete]);
5019 - (void)applyStyle:(DOMCSSStyleDeclaration *)style
5021 // We don't know enough at thls level to pass in a relevant WebUndoAction; we'd have to
5022 // change the API to allow this.
5023 WebFrame *webFrame = [self _selectedOrMainFrame];
5024 Frame* coreFrame = core(webFrame);
5026 coreFrame->editor()->applyStyle(core(style));
5031 @implementation WebView (WebViewEditingActions)
5033 - (void)_performResponderOperation:(SEL)selector with:(id)parameter
5035 static BOOL reentered = NO;
5037 [[self nextResponder] tryToPerform:selector with:parameter];
5041 // There are two possibilities here.
5043 // One is that WebView has been called in its role as part of the responder chain.
5044 // In that case, it's fine to call the first responder and end up calling down the
5045 // responder chain again. Later we will return here with reentered = YES and continue
5046 // past the WebView.
5048 // The other is that we are being called directly, in which case we want to pass the
5049 // selector down to the view inside us that can handle it, and continue down the
5050 // responder chain as usual.
5052 // Pass this selector down to the first responder.
5053 NSResponder *responder = [self _responderForResponderOperations];
5055 [responder tryToPerform:selector with:parameter];
5059 #define FORWARD(name) \
5060 - (void)name:(id)sender { [self _performResponderOperation:_cmd with:sender]; }
5062 FOR_EACH_RESPONDER_SELECTOR(FORWARD)
5064 - (void)insertText:(NSString *)text
5066 [self _performResponderOperation:_cmd with:text];
5071 @implementation WebView (WebViewEditingInMail)
5073 - (void)_insertNewlineInQuotedContent
5075 [[self _selectedOrMainFrame] _insertParagraphSeparatorInQuotedContent];
5078 - (void)_replaceSelectionWithNode:(DOMNode *)node matchStyle:(BOOL)matchStyle
5080 [[self _selectedOrMainFrame] _replaceSelectionWithNode:node selectReplacement:YES smartReplace:NO matchStyle:matchStyle];
5083 - (BOOL)_selectionIsCaret
5085 Frame* coreFrame = core([self _selectedOrMainFrame]);
5088 return coreFrame->selection()->isCaret();
5091 - (BOOL)_selectionIsAll
5093 Frame* coreFrame = core([self _selectedOrMainFrame]);
5096 return coreFrame->selection()->isAll(MayLeaveEditableContent);
5101 static WebFrameView *containingFrameView(NSView *view)
5103 while (view && ![view isKindOfClass:[WebFrameView class]])
5104 view = [view superview];
5105 return (WebFrameView *)view;
5108 @implementation WebView (WebFileInternal)
5110 + (void)_setCacheModel:(WebCacheModel)cacheModel
5112 if (s_didSetCacheModel && cacheModel == s_cacheModel)
5115 NSString *nsurlCacheDirectory = (NSString *)WebCFAutorelease(WKCopyFoundationCacheDirectory());
5116 if (!nsurlCacheDirectory)
5117 nsurlCacheDirectory = NSHomeDirectory();
5119 // As a fudge factor, use 1000 instead of 1024, in case the reported byte
5120 // count doesn't align exactly to a megabyte boundary.
5121 uint64_t memSize = WebMemorySize() / 1024 / 1000;
5122 unsigned long long diskFreeSize = WebVolumeFreeSize(nsurlCacheDirectory) / 1024 / 1000;
5123 NSURLCache *nsurlCache = [NSURLCache sharedURLCache];
5125 unsigned cacheTotalCapacity = 0;
5126 unsigned cacheMinDeadCapacity = 0;
5127 unsigned cacheMaxDeadCapacity = 0;
5128 double deadDecodedDataDeletionInterval = 0;
5130 unsigned pageCacheCapacity = 0;
5132 NSUInteger nsurlCacheMemoryCapacity = 0;
5133 NSUInteger nsurlCacheDiskCapacity = 0;
5135 switch (cacheModel) {
5136 case WebCacheModelDocumentViewer: {
5137 // Page cache capacity (in pages)
5138 pageCacheCapacity = 0;
5140 // Object cache capacities (in bytes)
5141 if (memSize >= 2048)
5142 cacheTotalCapacity = 96 * 1024 * 1024;
5143 else if (memSize >= 1536)
5144 cacheTotalCapacity = 64 * 1024 * 1024;
5145 else if (memSize >= 1024)
5146 cacheTotalCapacity = 32 * 1024 * 1024;
5147 else if (memSize >= 512)
5148 cacheTotalCapacity = 16 * 1024 * 1024;
5150 cacheMinDeadCapacity = 0;
5151 cacheMaxDeadCapacity = 0;
5153 // Foundation memory cache capacity (in bytes)
5154 nsurlCacheMemoryCapacity = 0;
5156 // Foundation disk cache capacity (in bytes)
5157 nsurlCacheDiskCapacity = [nsurlCache diskCapacity];
5161 case WebCacheModelDocumentBrowser: {
5162 // Page cache capacity (in pages)
5163 if (memSize >= 1024)
5164 pageCacheCapacity = 3;
5165 else if (memSize >= 512)
5166 pageCacheCapacity = 2;
5167 else if (memSize >= 256)
5168 pageCacheCapacity = 1;
5170 pageCacheCapacity = 0;
5172 // Object cache capacities (in bytes)
5173 if (memSize >= 2048)
5174 cacheTotalCapacity = 96 * 1024 * 1024;
5175 else if (memSize >= 1536)
5176 cacheTotalCapacity = 64 * 1024 * 1024;
5177 else if (memSize >= 1024)
5178 cacheTotalCapacity = 32 * 1024 * 1024;
5179 else if (memSize >= 512)
5180 cacheTotalCapacity = 16 * 1024 * 1024;
5182 cacheMinDeadCapacity = cacheTotalCapacity / 8;
5183 cacheMaxDeadCapacity = cacheTotalCapacity / 4;
5185 // Foundation memory cache capacity (in bytes)
5186 if (memSize >= 2048)
5187 nsurlCacheMemoryCapacity = 4 * 1024 * 1024;
5188 else if (memSize >= 1024)
5189 nsurlCacheMemoryCapacity = 2 * 1024 * 1024;
5190 else if (memSize >= 512)
5191 nsurlCacheMemoryCapacity = 1 * 1024 * 1024;
5193 nsurlCacheMemoryCapacity = 512 * 1024;
5195 // Foundation disk cache capacity (in bytes)
5196 if (diskFreeSize >= 16384)
5197 nsurlCacheDiskCapacity = 50 * 1024 * 1024;
5198 else if (diskFreeSize >= 8192)
5199 nsurlCacheDiskCapacity = 40 * 1024 * 1024;
5200 else if (diskFreeSize >= 4096)
5201 nsurlCacheDiskCapacity = 30 * 1024 * 1024;
5203 nsurlCacheDiskCapacity = 20 * 1024 * 1024;
5207 case WebCacheModelPrimaryWebBrowser: {
5208 // Page cache capacity (in pages)
5209 // (Research indicates that value / page drops substantially after 3 pages.)
5210 if (memSize >= 2048)
5211 pageCacheCapacity = 5;
5212 else if (memSize >= 1024)
5213 pageCacheCapacity = 4;
5214 else if (memSize >= 512)
5215 pageCacheCapacity = 3;
5216 else if (memSize >= 256)
5217 pageCacheCapacity = 2;
5219 pageCacheCapacity = 1;
5221 // Object cache capacities (in bytes)
5222 // (Testing indicates that value / MB depends heavily on content and
5223 // browsing pattern. Even growth above 128MB can have substantial
5224 // value / MB for some content / browsing patterns.)
5225 if (memSize >= 2048)
5226 cacheTotalCapacity = 128 * 1024 * 1024;
5227 else if (memSize >= 1536)
5228 cacheTotalCapacity = 96 * 1024 * 1024;
5229 else if (memSize >= 1024)
5230 cacheTotalCapacity = 64 * 1024 * 1024;
5231 else if (memSize >= 512)
5232 cacheTotalCapacity = 32 * 1024 * 1024;
5234 cacheMinDeadCapacity = cacheTotalCapacity / 4;
5235 cacheMaxDeadCapacity = cacheTotalCapacity / 2;
5237 // This code is here to avoid a PLT regression. We can remove it if we
5238 // can prove that the overall system gain would justify the regression.
5239 cacheMaxDeadCapacity = max(24u, cacheMaxDeadCapacity);
5241 deadDecodedDataDeletionInterval = 60;
5243 // Foundation memory cache capacity (in bytes)
5244 // (These values are small because WebCore does most caching itself.)
5245 if (memSize >= 1024)
5246 nsurlCacheMemoryCapacity = 4 * 1024 * 1024;
5247 else if (memSize >= 512)
5248 nsurlCacheMemoryCapacity = 2 * 1024 * 1024;
5249 else if (memSize >= 256)
5250 nsurlCacheMemoryCapacity = 1 * 1024 * 1024;
5252 nsurlCacheMemoryCapacity = 512 * 1024;
5254 // Foundation disk cache capacity (in bytes)
5255 if (diskFreeSize >= 16384)
5256 nsurlCacheDiskCapacity = 175 * 1024 * 1024;
5257 else if (diskFreeSize >= 8192)
5258 nsurlCacheDiskCapacity = 150 * 1024 * 1024;
5259 else if (diskFreeSize >= 4096)
5260 nsurlCacheDiskCapacity = 125 * 1024 * 1024;
5261 else if (diskFreeSize >= 2048)
5262 nsurlCacheDiskCapacity = 100 * 1024 * 1024;
5263 else if (diskFreeSize >= 1024)
5264 nsurlCacheDiskCapacity = 75 * 1024 * 1024;
5266 nsurlCacheDiskCapacity = 50 * 1024 * 1024;
5271 ASSERT_NOT_REACHED();
5274 #ifdef BUILDING_ON_TIGER
5275 // Don't use a big Foundation disk cache on Tiger because, according to the
5276 // PLT, the Foundation disk cache on Tiger is slower than the network.
5277 nsurlCacheDiskCapacity = [nsurlCache diskCapacity];
5280 // Don't shrink a big disk cache, since that would cause churn.
5281 nsurlCacheDiskCapacity = max(nsurlCacheDiskCapacity, [nsurlCache diskCapacity]);
5283 cache()->setCapacities(cacheMinDeadCapacity, cacheMaxDeadCapacity, cacheTotalCapacity);
5284 cache()->setDeadDecodedDataDeletionInterval(deadDecodedDataDeletionInterval);
5285 pageCache()->setCapacity(pageCacheCapacity);
5286 [nsurlCache setMemoryCapacity:nsurlCacheMemoryCapacity];
5287 [nsurlCache setDiskCapacity:nsurlCacheDiskCapacity];
5289 s_cacheModel = cacheModel;
5290 s_didSetCacheModel = YES;
5293 + (WebCacheModel)_cacheModel
5295 return s_cacheModel;
5298 + (WebCacheModel)_didSetCacheModel
5300 return s_didSetCacheModel;
5303 + (WebCacheModel)_maxCacheModelInAnyInstance
5305 WebCacheModel cacheModel = WebCacheModelDocumentViewer;
5306 NSEnumerator *enumerator = [(NSMutableSet *)allWebViewsSet objectEnumerator];
5307 while (WebPreferences *preferences = [[enumerator nextObject] preferences])
5308 cacheModel = max(cacheModel, [preferences cacheModel]);
5312 + (void)_preferencesChangedNotification:(NSNotification *)notification
5314 WebPreferences *preferences = (WebPreferences *)[notification object];
5315 ASSERT([preferences isKindOfClass:[WebPreferences class]]);
5317 WebCacheModel cacheModel = [preferences cacheModel];
5318 if (![self _didSetCacheModel] || cacheModel > [self _cacheModel])
5319 [self _setCacheModel:cacheModel];
5320 else if (cacheModel < [self _cacheModel])
5321 [self _setCacheModel:max([[WebPreferences standardPreferences] cacheModel], [self _maxCacheModelInAnyInstance])];
5324 + (void)_preferencesRemovedNotification:(NSNotification *)notification
5326 WebPreferences *preferences = (WebPreferences *)[notification object];
5327 ASSERT([preferences isKindOfClass:[WebPreferences class]]);
5329 if ([preferences cacheModel] == [self _cacheModel])
5330 [self _setCacheModel:max([[WebPreferences standardPreferences] cacheModel], [self _maxCacheModelInAnyInstance])];
5333 - (WebFrame *)_focusedFrame
5335 NSResponder *resp = [[self window] firstResponder];
5336 if (resp && [resp isKindOfClass:[NSView class]] && [(NSView *)resp isDescendantOf:[[self mainFrame] frameView]]) {
5337 WebFrameView *frameView = containingFrameView((NSView *)resp);
5338 ASSERT(frameView != nil);
5339 return [frameView webFrame];
5347 WebFrame *mainFrame = [self mainFrame];
5348 return [[mainFrame _dataSource] isLoading]
5349 || [[mainFrame provisionalDataSource] isLoading];
5352 - (WebFrameView *)_frameViewAtWindowPoint:(NSPoint)point
5354 if (_private->closed)
5356 ASSERT(_private->usesDocumentViews);
5357 NSView *view = [self hitTest:[[self superview] convertPoint:point fromView:nil]];
5358 if (![view isDescendantOf:[[self mainFrame] frameView]])
5360 WebFrameView *frameView = containingFrameView(view);
5365 + (void)_preflightSpellCheckerNow:(id)sender
5367 [[NSSpellChecker sharedSpellChecker] _preflightChosenSpellServer];
5370 + (void)_preflightSpellChecker
5372 // As AppKit does, we wish to delay tickling the shared spellchecker into existence on application launch.
5373 if ([NSSpellChecker sharedSpellCheckerExists]) {
5374 [self _preflightSpellCheckerNow:self];
5376 [self performSelector:@selector(_preflightSpellCheckerNow:) withObject:self afterDelay:2.0];
5380 - (BOOL)_continuousCheckingAllowed
5382 static BOOL allowContinuousSpellChecking = YES;
5383 static BOOL readAllowContinuousSpellCheckingDefault = NO;
5384 if (!readAllowContinuousSpellCheckingDefault) {
5385 if ([[NSUserDefaults standardUserDefaults] objectForKey:@"NSAllowContinuousSpellChecking"]) {
5386 allowContinuousSpellChecking = [[NSUserDefaults standardUserDefaults] boolForKey:@"NSAllowContinuousSpellChecking"];
5388 readAllowContinuousSpellCheckingDefault = YES;
5390 return allowContinuousSpellChecking;
5393 - (NSResponder *)_responderForResponderOperations
5395 NSResponder *responder = [[self window] firstResponder];
5396 WebFrameView *mainFrameView = [[self mainFrame] frameView];
5398 // If the current responder is outside of the webview, use our main frameView or its
5399 // document view. We also do this for subviews of self that are siblings of the main
5400 // frameView since clients might insert non-webview-related views there (see 4552713).
5401 if (responder != self && ![mainFrameView _web_firstResponderIsSelfOrDescendantView]) {
5402 responder = [mainFrameView documentView];
5404 responder = mainFrameView;
5409 - (void)_openFrameInNewWindowFromMenu:(NSMenuItem *)sender
5411 ASSERT_ARG(sender, [sender isKindOfClass:[NSMenuItem class]]);
5413 NSDictionary *element = [sender representedObject];
5414 ASSERT([element isKindOfClass:[NSDictionary class]]);
5416 WebDataSource *dataSource = [(WebFrame *)[element objectForKey:WebElementFrameKey] dataSource];
5417 NSURLRequest *request = [[dataSource request] copy];
5420 [self _openNewWindowWithRequest:request];
5424 - (void)_searchWithGoogleFromMenu:(id)sender
5426 id documentView = [[[self selectedFrame] frameView] documentView];
5427 if (![documentView conformsToProtocol:@protocol(WebDocumentText)]) {
5431 NSString *selectedString = [(id <WebDocumentText>)documentView selectedString];
5432 if ([selectedString length] == 0) {
5436 NSPasteboard *pasteboard = [NSPasteboard pasteboardWithUniqueName];
5437 [pasteboard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
5438 NSMutableString *s = [selectedString mutableCopy];
5439 const unichar nonBreakingSpaceCharacter = 0xA0;
5440 NSString *nonBreakingSpaceString = [NSString stringWithCharacters:&nonBreakingSpaceCharacter length:1];
5441 [s replaceOccurrencesOfString:nonBreakingSpaceString withString:@" " options:0 range:NSMakeRange(0, [s length])];
5442 [pasteboard setString:s forType:NSStringPboardType];
5445 // FIXME: seems fragile to use the service by name, but this is what AppKit does
5446 NSPerformService(@"Search With Google", pasteboard);
5449 - (void)_searchWithSpotlightFromMenu:(id)sender
5451 id documentView = [[[self selectedFrame] frameView] documentView];
5452 if (![documentView conformsToProtocol:@protocol(WebDocumentText)])
5455 NSString *selectedString = [(id <WebDocumentText>)documentView selectedString];
5456 if (![selectedString length])
5459 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
5460 [[NSWorkspace sharedWorkspace] showSearchResultsForQueryString:selectedString];
5462 (void)HISearchWindowShow((CFStringRef)selectedString, kNilOptions);
5466 #if USE(ACCELERATED_COMPOSITING)
5467 - (void)_clearLayerSyncLoopObserver
5469 if (!_private->layerSyncRunLoopObserver)
5472 CFRunLoopObserverInvalidate(_private->layerSyncRunLoopObserver);
5473 CFRelease(_private->layerSyncRunLoopObserver);
5474 _private->layerSyncRunLoopObserver = 0;
5478 #if ENABLE(VIDEO) && USE(GSTREAMER)
5479 - (void)_clearGlibLoopObserver
5481 if (!_private->glibRunLoopObserver)
5484 CFRunLoopObserverInvalidate(_private->glibRunLoopObserver);
5485 CFRelease(_private->glibRunLoopObserver);
5486 _private->glibRunLoopObserver = 0;
5491 @implementation WebView (WebViewInternal)
5493 + (BOOL)shouldIncludeInWebKitStatistics
5498 - (BOOL)_becomingFirstResponderFromOutside
5500 return _private->becomingFirstResponderFromOutside;
5503 #if ENABLE(ICONDATABASE)
5504 - (void)_receivedIconChangedNotification:(NSNotification *)notification
5506 // Get the URL for this notification
5507 NSDictionary *userInfo = [notification userInfo];
5508 ASSERT([userInfo isKindOfClass:[NSDictionary class]]);
5509 NSString *urlString = [userInfo objectForKey:WebIconNotificationUserInfoURLKey];
5510 ASSERT([urlString isKindOfClass:[NSString class]]);
5512 // If that URL matches the current main frame, dispatch the delegate call, which will also unregister
5513 // us for this notification
5514 if ([[self mainFrameURL] isEqualTo:urlString])
5515 [self _dispatchDidReceiveIconFromWebFrame:[self mainFrame]];
5518 - (void)_registerForIconNotification:(BOOL)listen
5521 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_receivedIconChangedNotification:) name:WebIconDatabaseDidAddIconNotification object:nil];
5523 [[NSNotificationCenter defaultCenter] removeObserver:self name:WebIconDatabaseDidAddIconNotification object:nil];
5526 - (void)_dispatchDidReceiveIconFromWebFrame:(WebFrame *)webFrame
5528 // FIXME: This willChangeValueForKey call is too late, because the icon has already changed by now.
5529 [self _willChangeValueForKey:_WebMainFrameIconKey];
5531 // 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
5532 // notification any longer
5533 [self _registerForIconNotification:NO];
5535 WebFrameLoadDelegateImplementationCache* cache = &_private->frameLoadDelegateImplementations;
5536 if (cache->didReceiveIconForFrameFunc) {
5537 Image* image = iconDatabase()->iconForPageURL(core(webFrame)->loader()->url().string(), IntSize(16, 16));
5538 if (NSImage *icon = webGetNSImage(image, NSMakeSize(16, 16)))
5539 CallFrameLoadDelegate(cache->didReceiveIconForFrameFunc, self, @selector(webView:didReceiveIcon:forFrame:), icon, webFrame);
5542 [self _didChangeValueForKey:_WebMainFrameIconKey];
5544 #endif // ENABLE(ICONDATABASE)
5546 - (void)_addObject:(id)object forIdentifier:(unsigned long)identifier
5548 ASSERT(!_private->identifierMap.contains(identifier));
5550 // If the identifier map is initially empty it means we're starting a load
5551 // of something. The semantic is that the web view should be around as long
5552 // as something is loading. Because of that we retain the web view.
5553 if (_private->identifierMap.isEmpty())
5556 _private->identifierMap.set(identifier, object);
5559 - (id)_objectForIdentifier:(unsigned long)identifier
5561 return _private->identifierMap.get(identifier).get();
5564 - (void)_removeObjectForIdentifier:(unsigned long)identifier
5566 ASSERT(_private->identifierMap.contains(identifier));
5567 _private->identifierMap.remove(identifier);
5569 // If the identifier map is now empty it means we're no longer loading anything
5570 // and we should release the web view.
5571 if (_private->identifierMap.isEmpty())
5575 - (void)_retrieveKeyboardUIModeFromPreferences:(NSNotification *)notification
5577 CFPreferencesAppSynchronize(UniversalAccessDomain);
5579 Boolean keyExistsAndHasValidFormat;
5580 int mode = CFPreferencesGetAppIntegerValue(AppleKeyboardUIMode, UniversalAccessDomain, &keyExistsAndHasValidFormat);
5582 // The keyboard access mode is reported by two bits:
5583 // Bit 0 is set if feature is on
5584 // Bit 1 is set if full keyboard access works for any control, not just text boxes and lists
5585 // We require both bits to be on.
5586 // I do not know that we would ever get one bit on and the other off since
5587 // checking the checkbox in system preferences which is marked as "Turn on full keyboard access"
5588 // turns on both bits.
5589 _private->_keyboardUIMode = (mode & 0x2) ? KeyboardAccessFull : KeyboardAccessDefault;
5591 // check for tabbing to links
5592 if ([_private->preferences tabsToLinks])
5593 _private->_keyboardUIMode = (KeyboardUIMode)(_private->_keyboardUIMode | KeyboardAccessTabsToLinks);
5596 - (KeyboardUIMode)_keyboardUIMode
5598 if (!_private->_keyboardUIModeAccessed) {
5599 _private->_keyboardUIModeAccessed = YES;
5601 [self _retrieveKeyboardUIModeFromPreferences:nil];
5603 [[NSDistributedNotificationCenter defaultCenter]
5604 addObserver:self selector:@selector(_retrieveKeyboardUIModeFromPreferences:)
5605 name:KeyboardUIModeDidChangeNotification object:nil];
5607 [[NSNotificationCenter defaultCenter]
5608 addObserver:self selector:@selector(_retrieveKeyboardUIModeFromPreferences:)
5609 name:WebPreferencesChangedNotification object:nil];
5611 return _private->_keyboardUIMode;
5614 - (void)_setInsertionPasteboard:(NSPasteboard *)pasteboard
5616 _private->insertionPasteboard = pasteboard;
5619 - (void)_selectionChanged
5621 if (_private->usesDocumentViews) {
5622 id documentView = [[[self _selectedOrMainFrame] frameView] documentView];
5623 if ([documentView isKindOfClass:[WebHTMLView class]])
5624 [documentView _selectionChanged];
5628 // FIXME (Viewless): We'll need code here.
5631 - (Frame*)_mainCoreFrame
5633 return (_private && _private->page) ? _private->page->mainFrame() : 0;
5636 - (WebFrame *)_selectedOrMainFrame
5638 WebFrame *result = [self selectedFrame];
5640 result = [self mainFrame];
5644 #if USE(ACCELERATED_COMPOSITING)
5646 - (BOOL)_needsOneShotDrawingSynchronization
5648 return _private->needsOneShotDrawingSynchronization;
5651 - (void)_setNeedsOneShotDrawingSynchronization:(BOOL)needsSynchronization
5653 _private->needsOneShotDrawingSynchronization = needsSynchronization;
5656 - (BOOL)_syncCompositingChanges
5658 Frame* frame = [self _mainCoreFrame];
5659 if (frame && frame->view())
5660 return frame->view()->syncCompositingStateRecursive();
5666 The order of events with compositing updates is this:
5668 Start of runloop End of runloop
5670 --|-------------------------------------------------------|--
5673 NSWindow update, | CA commit
5676 layerSyncRunLoopObserverCallBack
5678 To avoid flashing, we have to ensure that compositing changes (rendered via
5679 the CoreAnimation rendering display link) appear on screen at the same time
5680 as content painted into the window via the normal WebCore rendering path.
5682 CoreAnimation will commit any layer changes at the end of the runloop via
5683 its "CA commit" observer. Those changes can then appear onscreen at any time
5684 when the display link fires, which can result in unsynchronized rendering.
5686 To fix this, the GraphicsLayerCA code in WebCore does not change the CA
5687 layer tree during style changes and layout; it stores up all changes and
5688 commits them via syncCompositingState(). There are then two situations in
5689 which we can call syncCompositingState():
5691 1. When painting. FrameView::paintContents() makes a call to syncCompositingState().
5693 2. When style changes/layout have made changes to the layer tree which do not
5694 result in painting. In this case we need a run loop observer to do a
5695 syncCompositingState() at an appropriate time. The observer will keep firing
5696 until the time is right (essentially when there are no more pending layouts).
5700 static void layerSyncRunLoopObserverCallBack(CFRunLoopObserverRef, CFRunLoopActivity, void* info)
5702 WebView *webView = reinterpret_cast<WebView*>(info);
5703 NSWindow *window = [webView window];
5705 // An NSWindow may not display in the next runloop cycle after dirtying due to delayed window display logic,
5706 // in which case this observer can fire first. So if the window is due for a display, don't commit
5707 // layer changes, otherwise they'll show on screen before the view drawing.
5708 bool viewsNeedDisplay;
5710 if (window && [window _wrapsCarbonWindow])
5711 viewsNeedDisplay = HIViewGetNeedsDisplay(HIViewGetRoot(static_cast<WindowRef>([window windowRef])));
5714 viewsNeedDisplay = [window viewsNeedDisplay];
5716 if (viewsNeedDisplay)
5719 if ([webView _syncCompositingChanges]) {
5720 [webView _clearLayerSyncLoopObserver];
5721 // AppKit may have disabled screen updates, thinking an upcoming window flush will re-enable them.
5722 // In case setNeedsDisplayInRect() has prevented the window from needing to be flushed, re-enable screen
5724 if (![window isFlushWindowDisabled])
5725 [window _enableScreenUpdatesIfNeeded];
5727 // Since the WebView does not need display, -viewWillDraw will not be called. Perform pending layout now,
5728 // so that the layers draw with up-to-date layout.
5729 [webView _viewWillDrawInternal];
5733 - (void)_scheduleCompositingLayerSync
5735 if (_private->layerSyncRunLoopObserver)
5738 // Run after AppKit does its window update. If we do any painting, we'll commit
5739 // layer changes from FrameView::paintContents(), otherwise we'll commit via
5740 // _syncCompositingChanges when this observer fires.
5741 const CFIndex runLoopOrder = NSDisplayWindowRunLoopOrdering + 1;
5743 // The WebView always outlives the observer, so no need to retain/release.
5744 CFRunLoopObserverContext context = { 0, self, 0, 0, 0 };
5746 _private->layerSyncRunLoopObserver = CFRunLoopObserverCreate(NULL,
5747 kCFRunLoopBeforeWaiting | kCFRunLoopExit, true /* repeats */,
5748 runLoopOrder, layerSyncRunLoopObserverCallBack, &context);
5750 CFRunLoopAddObserver(CFRunLoopGetCurrent(), _private->layerSyncRunLoopObserver, kCFRunLoopCommonModes);
5757 - (void)_enterFullscreenForNode:(WebCore::Node*)node
5759 ASSERT(node->hasTagName(WebCore::HTMLNames::videoTag));
5760 HTMLMediaElement* videoElement = static_cast<HTMLMediaElement*>(node);
5762 if (_private->fullscreenController) {
5763 if ([_private->fullscreenController mediaElement] == videoElement) {
5764 // The backend may just warn us that the underlaying plaftormMovie()
5765 // has changed. Just force an update.
5766 [_private->fullscreenController setMediaElement:videoElement];
5767 return; // No more to do.
5770 // First exit Fullscreen for the old mediaElement.
5771 [_private->fullscreenController mediaElement]->exitFullscreen();
5772 // This previous call has to trigger _exitFullscreen,
5773 // which has to clear _private->fullscreenController.
5774 ASSERT(!_private->fullscreenController);
5776 if (!_private->fullscreenController) {
5777 _private->fullscreenController = [[WebVideoFullscreenController alloc] init];
5778 [_private->fullscreenController setMediaElement:videoElement];
5779 [_private->fullscreenController enterFullscreen:[[self window] screen]];
5782 [_private->fullscreenController setMediaElement:videoElement];
5785 - (void)_exitFullscreen
5787 if (!_private->fullscreenController)
5789 [_private->fullscreenController exitFullscreen];
5790 [_private->fullscreenController release];
5791 _private->fullscreenController = nil;
5796 #if ENABLE(VIDEO) && USE(GSTREAMER)
5798 static void glibContextIterationCallback(CFRunLoopObserverRef, CFRunLoopActivity, void*)
5800 g_main_context_iteration(0, FALSE);
5803 - (void)_scheduleGlibContextIterations
5805 if (_private->glibRunLoopObserver)
5808 NSRunLoop* myRunLoop = [NSRunLoop currentRunLoop];
5810 // Create a run loop observer and attach it to the run loop.
5811 CFRunLoopObserverContext context = {0, self, 0, 0, 0};
5812 _private->glibRunLoopObserver = CFRunLoopObserverCreate(kCFAllocatorDefault, kCFRunLoopBeforeWaiting, YES, 0, &glibContextIterationCallback, &context);
5814 if (_private->glibRunLoopObserver) {
5815 CFRunLoopRef cfLoop = [myRunLoop getCFRunLoop];
5816 CFRunLoopAddObserver(cfLoop, _private->glibRunLoopObserver, kCFRunLoopDefaultMode);
5825 @implementation WebView (WebViewGeolocation)
5827 - (void)_setGeolocationProvider:(id<WebGeolocationProvider>)geolocationProvider
5830 _private->_geolocationProvider = geolocationProvider;
5833 - (id<WebGeolocationProvider>)_geolocationProvider
5836 return _private->_geolocationProvider;
5840 - (void)_geolocationDidChangePosition:(WebGeolocationPosition *)position
5842 #if ENABLE(CLIENT_BASED_GEOLOCATION)
5843 if (_private && _private->page)
5844 _private->page->geolocationController()->positionChanged(core(position));
5848 - (void)_geolocationDidFailWithError:(NSError *)error
5850 #if ENABLE(CLIENT_BASED_GEOLOCATION)
5851 if (_private && _private->page) {
5852 RefPtr<GeolocationError> geolocatioError = GeolocationError::create(GeolocationError::PositionUnavailable, [error localizedDescription]);
5853 _private->page->geolocationController()->errorOccurred(geolocatioError.get());
5860 @implementation WebView (WebViewPrivateStyleInfo)
5862 - (JSValueRef)_computedStyleIncludingVisitedInfo:(JSContextRef)context forElement:(JSValueRef)value
5864 JSLock lock(SilenceAssertionsOnly);
5865 ExecState* exec = toJS(context);
5867 return JSValueMakeUndefined(context);
5868 JSValue jsValue = toJS(exec, value);
5869 if (!jsValue.inherits(&JSElement::s_info))
5870 return JSValueMakeUndefined(context);
5871 JSElement* jsElement = static_cast<JSElement*>(asObject(jsValue));
5872 Element* element = jsElement->impl();
5873 RefPtr<CSSComputedStyleDeclaration> style = computedStyle(element, true);
5874 return toRef(exec, toJS(exec, jsElement->globalObject(), style.get()));
5879 #ifdef BUILDING_ON_LEOPARD
5881 static IMP originalRecursivelyRemoveMailAttributesImp;
5883 static id objectElementDataAttribute(DOMHTMLObjectElement *self, SEL)
5885 return [self getAttribute:@"data"];
5888 static void recursivelyRemoveMailAttributes(DOMNode *self, SEL selector, BOOL a, BOOL b, BOOL c)
5890 // While inside this Mail function, change the behavior of -[DOMHTMLObjectElement data] back to what it used to be
5891 // before we fixed a bug in it (see http://trac.webkit.org/changeset/30044 for that change).
5893 // It's a little bit strange to patch a method defined by WebKit, but it helps keep this workaround self-contained.
5895 Method methodToPatch = class_getInstanceMethod(objc_getRequiredClass("DOMHTMLObjectElement"), @selector(data));
5896 IMP originalDataImp = method_setImplementation(methodToPatch, reinterpret_cast<IMP>(objectElementDataAttribute));
5897 originalRecursivelyRemoveMailAttributesImp(self, selector, a, b, c);
5898 method_setImplementation(methodToPatch, originalDataImp);
5903 static void patchMailRemoveAttributesMethod()
5905 #ifdef BUILDING_ON_LEOPARD
5906 if (!WKAppVersionCheckLessThan(@"com.apple.mail", -1, 4.0))
5908 Method methodToPatch = class_getInstanceMethod(objc_getRequiredClass("DOMNode"), @selector(recursivelyRemoveMailAttributes:convertObjectsToImages:convertEditableElements:));
5911 originalRecursivelyRemoveMailAttributesImp = method_setImplementation(methodToPatch, reinterpret_cast<IMP>(recursivelyRemoveMailAttributes));