2 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
3 * Copyright (C) 2006 David Smith (catfish.man@gmail.com)
4 * Copyright (C) 2010 Igalia S.L
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
16 * its contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #import "WebViewInternal.h"
32 #import "WebViewData.h"
34 #import "DOMCSSStyleDeclarationInternal.h"
35 #import "DOMNodeInternal.h"
36 #import "DOMRangeInternal.h"
37 #import "WebBackForwardListInternal.h"
38 #import "WebBaseNetscapePluginView.h"
40 #import "WebChromeClient.h"
41 #import "WebContextMenuClient.h"
42 #import "WebDOMOperationsPrivate.h"
43 #import "WebDataSourceInternal.h"
44 #import "WebDatabaseManagerInternal.h"
45 #import "WebDefaultEditingDelegate.h"
46 #import "WebDefaultPolicyDelegate.h"
47 #import "WebDefaultUIDelegate.h"
48 #import "WebDelegateImplementationCaching.h"
49 #import "WebDocument.h"
50 #import "WebDocumentInternal.h"
51 #import "WebDownload.h"
52 #import "WebDownloadInternal.h"
53 #import "WebDragClient.h"
54 #import "WebDynamicScrollBarsViewInternal.h"
55 #import "WebEditingDelegate.h"
56 #import "WebEditorClient.h"
57 #import "WebFormDelegatePrivate.h"
58 #import "WebFrameInternal.h"
59 #import "WebFrameViewInternal.h"
60 #import "WebGeolocationControllerClient.h"
61 #import "WebGeolocationPositionInternal.h"
62 #import "WebHTMLRepresentation.h"
63 #import "WebHTMLViewInternal.h"
64 #import "WebHistoryItemInternal.h"
65 #import "WebIconDatabaseInternal.h"
66 #import "WebInspector.h"
67 #import "WebInspectorClient.h"
68 #import "WebKitErrors.h"
69 #import "WebKitLogging.h"
70 #import "WebKitNSStringExtras.h"
71 #import "WebKitStatisticsPrivate.h"
72 #import "WebKitSystemBits.h"
73 #import "WebKitVersionChecks.h"
74 #import "WebLocalizableStrings.h"
75 #import "WebNSDataExtras.h"
76 #import "WebNSDataExtrasPrivate.h"
77 #import "WebNSDictionaryExtras.h"
78 #import "WebNSEventExtras.h"
79 #import "WebNSObjectExtras.h"
80 #import "WebNSPasteboardExtras.h"
81 #import "WebNSPrintOperationExtras.h"
82 #import "WebNSURLExtras.h"
83 #import "WebNSURLRequestExtras.h"
84 #import "WebNSUserDefaultsExtras.h"
85 #import "WebNSViewExtras.h"
86 #import "WebNodeHighlight.h"
87 #import "WebPDFView.h"
88 #import "WebPanelAuthenticationHandler.h"
89 #import "WebPasteboardHelper.h"
90 #import "WebPlatformStrategies.h"
91 #import "WebPluginDatabase.h"
92 #import "WebPluginHalterClient.h"
93 #import "WebPolicyDelegate.h"
94 #import "WebPreferenceKeysPrivate.h"
95 #import "WebPreferencesPrivate.h"
96 #import "WebScriptDebugDelegate.h"
97 #import "WebScriptWorldInternal.h"
98 #import "WebSystemInterface.h"
99 #import "WebTextCompletionController.h"
100 #import "WebTextIterator.h"
101 #import "WebUIDelegate.h"
102 #import "WebUIDelegatePrivate.h"
103 #import "WebVideoFullscreenController.h"
104 #import <CoreFoundation/CFSet.h>
105 #import <Foundation/NSURLConnection.h>
106 #import <JavaScriptCore/APICast.h>
107 #import <JavaScriptCore/JSValueRef.h>
108 #import <WebCore/AbstractDatabase.h>
109 #import <WebCore/ApplicationCacheStorage.h>
110 #import <WebCore/BackForwardList.h>
111 #import <WebCore/Cache.h>
112 #import <WebCore/ColorMac.h>
113 #import <WebCore/CSSComputedStyleDeclaration.h>
114 #import <WebCore/Cursor.h>
115 #import <WebCore/Document.h>
116 #import <WebCore/DocumentLoader.h>
117 #import <WebCore/DragController.h>
118 #import <WebCore/DragData.h>
119 #import <WebCore/Editor.h>
120 #import <WebCore/EventHandler.h>
121 #import <WebCore/ExceptionHandlers.h>
122 #import <WebCore/FocusController.h>
123 #import <WebCore/Frame.h>
124 #import <WebCore/FrameLoader.h>
125 #import <WebCore/FrameTree.h>
126 #import <WebCore/FrameView.h>
127 #import <WebCore/GCController.h>
128 #import <WebCore/HTMLMediaElement.h>
129 #import <WebCore/HTMLNames.h>
130 #import <WebCore/HistoryItem.h>
131 #import <WebCore/IconDatabase.h>
132 #import <WebCore/JSCSSStyleDeclaration.h>
133 #import <WebCore/JSElement.h>
134 #import <WebCore/Logging.h>
135 #import <WebCore/MIMETypeRegistry.h>
136 #import <WebCore/Page.h>
137 #import <WebCore/PageCache.h>
138 #import <WebCore/PageGroup.h>
139 #import <WebCore/PlatformMouseEvent.h>
140 #import <WebCore/ProgressTracker.h>
141 #import <WebCore/RenderWidget.h>
142 #import <WebCore/ResourceHandle.h>
143 #import <WebCore/RuntimeApplicationChecks.h>
144 #import <WebCore/SchemeRegistry.h>
145 #import <WebCore/ScriptController.h>
146 #import <WebCore/ScriptValue.h>
147 #import <WebCore/SecurityOrigin.h>
148 #import <WebCore/SelectionController.h>
149 #import <WebCore/Settings.h>
150 #import <WebCore/TextResourceDecoder.h>
151 #import <WebCore/ThreadCheck.h>
152 #import <WebCore/WebCoreObjCExtras.h>
153 #import <WebCore/WebCoreView.h>
154 #import <WebCore/Widget.h>
155 #import <WebKit/DOM.h>
156 #import <WebKit/DOMExtensions.h>
157 #import <WebKit/DOMPrivate.h>
158 #import <WebKitSystemInterface.h>
159 #import <mach-o/dyld.h>
160 #import <objc/objc-auto.h>
161 #import <objc/objc-runtime.h>
162 #import <runtime/ArrayPrototype.h>
163 #import <runtime/DateInstance.h>
164 #import <runtime/InitializeThreading.h>
165 #import <runtime/JSLock.h>
166 #import <runtime/JSValue.h>
167 #import <wtf/Assertions.h>
168 #import <wtf/HashTraits.h>
169 #import <wtf/RefCountedLeakCounter.h>
170 #import <wtf/RefPtr.h>
171 #import <wtf/StdLibExtras.h>
172 #import <wtf/Threading.h>
174 #if ENABLE(DASHBOARD_SUPPORT)
175 #import <WebKit/WebDashboardRegion.h>
178 #if ENABLE(CLIENT_BASED_GEOLOCATION)
179 #import <WebCore/GeolocationController.h>
180 #import <WebCore/GeolocationError.h>
183 #if ENABLE(VIDEO) && USE(GSTREAMER)
187 @interface NSSpellChecker (WebNSSpellCheckerDetails)
188 - (void)_preflightChosenSpellServer;
191 @interface NSView (WebNSViewDetails)
192 - (NSView *)_hitTest:(NSPoint *)aPoint dragTypes:(NSSet *)types;
193 - (void)_autoscrollForDraggingInfo:(id)dragInfo timeDelta:(NSTimeInterval)repeatDelta;
194 - (BOOL)_shouldAutoscrollForDraggingInfo:(id)dragInfo;
197 @interface NSWindow (WebNSWindowDetails)
198 - (id)_oldFirstResponderBeforeBecoming;
199 - (void)_enableScreenUpdatesIfNeeded;
200 - (BOOL)_wrapsCarbonWindow;
203 using namespace WebCore;
206 #if defined(__ppc__) || defined(__ppc64__)
207 #define PROCESSOR "PPC"
208 #elif defined(__i386__) || defined(__x86_64__)
209 #define PROCESSOR "Intel"
211 #error Unknown architecture
214 #define FOR_EACH_RESPONDER_SELECTOR(macro) \
216 macro(alignJustified) \
219 macro(capitalizeWord) \
220 macro(centerSelectionInVisibleArea) \
221 macro(changeAttributes) \
222 macro(changeBaseWritingDirection) \
223 macro(changeBaseWritingDirectionToLTR) \
224 macro(changeBaseWritingDirectionToRTL) \
226 macro(changeDocumentBackgroundColor) \
228 macro(changeSpelling) \
229 macro(checkSpelling) \
235 macro(deleteBackward) \
236 macro(deleteBackwardByDecomposingPreviousCharacter) \
237 macro(deleteForward) \
238 macro(deleteToBeginningOfLine) \
239 macro(deleteToBeginningOfParagraph) \
240 macro(deleteToEndOfLine) \
241 macro(deleteToEndOfParagraph) \
242 macro(deleteToMark) \
243 macro(deleteWordBackward) \
244 macro(deleteWordForward) \
245 macro(ignoreSpelling) \
247 macro(insertBacktab) \
248 macro(insertLineBreak) \
249 macro(insertNewline) \
250 macro(insertNewlineIgnoringFieldEditor) \
251 macro(insertParagraphSeparator) \
253 macro(insertTabIgnoringFieldEditor) \
254 macro(lowercaseWord) \
255 macro(makeBaseWritingDirectionLeftToRight) \
256 macro(makeBaseWritingDirectionRightToLeft) \
257 macro(makeTextWritingDirectionLeftToRight) \
258 macro(makeTextWritingDirectionNatural) \
259 macro(makeTextWritingDirectionRightToLeft) \
260 macro(moveBackward) \
261 macro(moveBackwardAndModifySelection) \
263 macro(moveDownAndModifySelection) \
265 macro(moveForwardAndModifySelection) \
267 macro(moveLeftAndModifySelection) \
268 macro(moveParagraphBackwardAndModifySelection) \
269 macro(moveParagraphForwardAndModifySelection) \
271 macro(moveRightAndModifySelection) \
272 macro(moveToBeginningOfDocument) \
273 macro(moveToBeginningOfDocumentAndModifySelection) \
274 macro(moveToBeginningOfLine) \
275 macro(moveToBeginningOfLineAndModifySelection) \
276 macro(moveToBeginningOfParagraph) \
277 macro(moveToBeginningOfParagraphAndModifySelection) \
278 macro(moveToBeginningOfSentence) \
279 macro(moveToBeginningOfSentenceAndModifySelection) \
280 macro(moveToEndOfDocument) \
281 macro(moveToEndOfDocumentAndModifySelection) \
282 macro(moveToEndOfLine) \
283 macro(moveToEndOfLineAndModifySelection) \
284 macro(moveToEndOfParagraph) \
285 macro(moveToEndOfParagraphAndModifySelection) \
286 macro(moveToEndOfSentence) \
287 macro(moveToEndOfSentenceAndModifySelection) \
288 macro(moveToLeftEndOfLine) \
289 macro(moveToLeftEndOfLineAndModifySelection) \
290 macro(moveToRightEndOfLine) \
291 macro(moveToRightEndOfLineAndModifySelection) \
293 macro(moveUpAndModifySelection) \
294 macro(moveWordBackward) \
295 macro(moveWordBackwardAndModifySelection) \
296 macro(moveWordForward) \
297 macro(moveWordForwardAndModifySelection) \
298 macro(moveWordLeft) \
299 macro(moveWordLeftAndModifySelection) \
300 macro(moveWordRight) \
301 macro(moveWordRightAndModifySelection) \
303 macro(orderFrontSubstitutionsPanel) \
305 macro(pageDownAndModifySelection) \
307 macro(pageUpAndModifySelection) \
309 macro(pasteAsPlainText) \
310 macro(pasteAsRichText) \
312 macro(performFindPanelAction) \
313 macro(scrollLineDown) \
314 macro(scrollLineUp) \
315 macro(scrollPageDown) \
316 macro(scrollPageUp) \
317 macro(scrollToBeginningOfDocument) \
318 macro(scrollToEndOfDocument) \
321 macro(selectParagraph) \
322 macro(selectSentence) \
323 macro(selectToMark) \
326 macro(showGuessPanel) \
327 macro(startSpeaking) \
328 macro(stopSpeaking) \
331 macro(swapWithMark) \
332 macro(takeFindStringFromSelection) \
333 macro(toggleBaseWritingDirection) \
337 macro(uppercaseWord) \
339 macro(yankAndSelect) \
341 #define WebKitOriginalTopPrintingMarginKey @"WebKitOriginalTopMargin"
342 #define WebKitOriginalBottomPrintingMarginKey @"WebKitOriginalBottomMargin"
344 #define KeyboardUIModeDidChangeNotification @"com.apple.KeyboardUIModeDidChange"
345 #define AppleKeyboardUIMode CFSTR("AppleKeyboardUIMode")
346 #define UniversalAccessDomain CFSTR("com.apple.universalaccess")
348 static BOOL s_didSetCacheModel;
349 static WebCacheModel s_cacheModel = WebCacheModelDocumentViewer;
352 static const char webViewIsOpen[] = "At least one WebView is still open.";
355 @interface NSObject (WebValidateWithoutDelegate)
356 - (BOOL)validateUserInterfaceItemWithoutDelegate:(id <NSValidatedUserInterfaceItem>)item;
359 @interface _WebSafeForwarder : NSObject
361 id target; // Non-retained. Don't retain delegates.
363 BOOL catchExceptions;
365 - (id)initWithTarget:(id)target defaultTarget:(id)defaultTarget catchExceptions:(BOOL)catchExceptions;
368 @interface WebView (WebFileInternal)
370 - (WebFrameView *)_frameViewAtWindowPoint:(NSPoint)point;
371 - (WebFrame *)_focusedFrame;
372 + (void)_preflightSpellChecker;
373 - (BOOL)_continuousCheckingAllowed;
374 - (NSResponder *)_responderForResponderOperations;
375 #if USE(ACCELERATED_COMPOSITING)
376 - (void)_clearLayerSyncLoopObserver;
378 #if ENABLE(VIDEO) && USE(GSTREAMER)
379 - (void)_clearGlibLoopObserver;
383 static void patchMailRemoveAttributesMethod();
385 NSString *WebElementDOMNodeKey = @"WebElementDOMNode";
386 NSString *WebElementFrameKey = @"WebElementFrame";
387 NSString *WebElementImageKey = @"WebElementImage";
388 NSString *WebElementImageAltStringKey = @"WebElementImageAltString";
389 NSString *WebElementImageRectKey = @"WebElementImageRect";
390 NSString *WebElementImageURLKey = @"WebElementImageURL";
391 NSString *WebElementIsSelectedKey = @"WebElementIsSelected";
392 NSString *WebElementLinkLabelKey = @"WebElementLinkLabel";
393 NSString *WebElementLinkTargetFrameKey = @"WebElementTargetFrame";
394 NSString *WebElementLinkTitleKey = @"WebElementLinkTitle";
395 NSString *WebElementLinkURLKey = @"WebElementLinkURL";
396 NSString *WebElementSpellingToolTipKey = @"WebElementSpellingToolTip";
397 NSString *WebElementTitleKey = @"WebElementTitle";
398 NSString *WebElementLinkIsLiveKey = @"WebElementLinkIsLive";
399 NSString *WebElementIsInScrollBarKey = @"WebElementIsInScrollBar";
400 NSString *WebElementIsContentEditableKey = @"WebElementIsContentEditableKey";
402 NSString *WebViewProgressStartedNotification = @"WebProgressStartedNotification";
403 NSString *WebViewProgressEstimateChangedNotification = @"WebProgressEstimateChangedNotification";
404 NSString *WebViewProgressFinishedNotification = @"WebProgressFinishedNotification";
406 NSString * const WebViewDidBeginEditingNotification = @"WebViewDidBeginEditingNotification";
407 NSString * const WebViewDidChangeNotification = @"WebViewDidChangeNotification";
408 NSString * const WebViewDidEndEditingNotification = @"WebViewDidEndEditingNotification";
409 NSString * const WebViewDidChangeTypingStyleNotification = @"WebViewDidChangeTypingStyleNotification";
410 NSString * const WebViewDidChangeSelectionNotification = @"WebViewDidChangeSelectionNotification";
412 enum { WebViewVersion = 4 };
414 #define timedLayoutSize 4096
416 static NSMutableSet *schemesWithRepresentationsSet;
418 NSString *_WebCanGoBackKey = @"canGoBack";
419 NSString *_WebCanGoForwardKey = @"canGoForward";
420 NSString *_WebEstimatedProgressKey = @"estimatedProgress";
421 NSString *_WebIsLoadingKey = @"isLoading";
422 NSString *_WebMainFrameIconKey = @"mainFrameIcon";
423 NSString *_WebMainFrameTitleKey = @"mainFrameTitle";
424 NSString *_WebMainFrameURLKey = @"mainFrameURL";
425 NSString *_WebMainFrameDocumentKey = @"mainFrameDocument";
427 NSString *_WebViewDidStartAcceleratedCompositingNotification = @"_WebViewDidStartAcceleratedCompositing";
429 @interface WebProgressItem : NSObject
432 long long bytesReceived;
433 long long estimatedLength;
437 @implementation WebProgressItem
440 static BOOL continuousSpellCheckingEnabled;
441 #ifndef BUILDING_ON_TIGER
442 static BOOL grammarCheckingEnabled;
444 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
445 static BOOL automaticQuoteSubstitutionEnabled;
446 static BOOL automaticLinkDetectionEnabled;
447 static BOOL automaticDashSubstitutionEnabled;
448 static BOOL automaticTextReplacementEnabled;
449 static BOOL automaticSpellingCorrectionEnabled;
452 @implementation WebView (AllWebViews)
454 static CFSetCallBacks NonRetainingSetCallbacks = {
463 static CFMutableSetRef allWebViewsSet;
465 + (void)_makeAllWebViewsPerformSelector:(SEL)selector
470 [(NSMutableSet *)allWebViewsSet makeObjectsPerformSelector:selector];
473 - (void)_removeFromAllWebViewsSet
476 CFSetRemoveValue(allWebViewsSet, self);
479 - (void)_addToAllWebViewsSet
482 allWebViewsSet = CFSetCreateMutable(NULL, 0, &NonRetainingSetCallbacks);
484 CFSetSetValue(allWebViewsSet, self);
489 @implementation WebView (WebPrivate)
491 static inline int callGestalt(OSType selector)
494 Gestalt(selector, &value);
498 // Uses underscores instead of dots because if "4." ever appears in a user agent string, old DHTML libraries treat it as Netscape 4.
499 static NSString *createMacOSXVersionString()
501 // Can't use -[NSProcessInfo operatingSystemVersionString] because it has too much stuff we don't want.
502 int major = callGestalt(gestaltSystemVersionMajor);
505 int minor = callGestalt(gestaltSystemVersionMinor);
506 int bugFix = callGestalt(gestaltSystemVersionBugFix);
508 return [[NSString alloc] initWithFormat:@"%d_%d_%d", major, minor, bugFix];
510 return [[NSString alloc] initWithFormat:@"%d_%d", major, minor];
511 return [[NSString alloc] initWithFormat:@"%d", major];
514 static NSString *createUserVisibleWebKitVersionString()
516 // If the version is 4 digits long or longer, then the first digit represents
517 // the version of the OS. Our user agent string should not include this first digit,
518 // so strip it off and report the rest as the version. <rdar://problem/4997547>
519 NSString *fullVersion = [[NSBundle bundleForClass:[WebView class]] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey];
520 NSRange nonDigitRange = [fullVersion rangeOfCharacterFromSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]];
521 if (nonDigitRange.location == NSNotFound && [fullVersion length] >= 4)
522 return [[fullVersion substringFromIndex:1] copy];
523 if (nonDigitRange.location != NSNotFound && nonDigitRange.location >= 4)
524 return [[fullVersion substringFromIndex:1] copy];
525 return [fullVersion copy];
528 + (NSString *)_standardUserAgentWithApplicationName:(NSString *)applicationName
530 // Note: Do *not* move the initialization of osVersion nor webKitVersion into the declaration.
531 // Garbage collection won't correctly mark the global variable in that case <rdar://problem/5733674>.
532 static NSString *osVersion;
533 static NSString *webKitVersion;
535 osVersion = createMacOSXVersionString();
537 webKitVersion = createUserVisibleWebKitVersionString();
538 NSString *language = [NSUserDefaults _webkit_preferredLanguageCode];
539 if ([applicationName length])
540 return [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; U; " PROCESSOR " Mac OS X %@; %@) AppleWebKit/%@ (KHTML, like Gecko) %@", osVersion, language, webKitVersion, applicationName];
541 return [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; U; " PROCESSOR " Mac OS X %@; %@) AppleWebKit/%@ (KHTML, like Gecko)", osVersion, language, webKitVersion];
544 + (void)_reportException:(JSValueRef)exception inContext:(JSContextRef)context
546 if (!exception || !context)
549 JSLock lock(SilenceAssertionsOnly);
550 JSC::ExecState* execState = toJS(context);
552 // Make sure the context has a DOMWindow global object, otherwise this context didn't originate from a WebView.
553 if (!toJSDOMWindow(execState->lexicalGlobalObject()))
556 reportException(execState, toJS(execState, exception));
559 static void WebKitInitializeApplicationCachePathIfNecessary()
561 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
562 static BOOL initialized = NO;
566 NSString *appName = [[NSBundle mainBundle] bundleIdentifier];
568 appName = [[NSProcessInfo processInfo] processName];
572 NSString* cacheDir = [NSString _webkit_localCacheDirectoryWithBundleIdentifier:appName];
574 cacheStorage().setCacheDirectory(cacheDir);
579 static bool runningLeopardMail()
581 #ifdef BUILDING_ON_LEOPARD
582 return applicationIsAppleMail();
587 static bool runningTigerMail()
589 #ifdef BUILDING_ON_TIGER
590 return applicationIsAppleMail();
595 static bool coreVideoHas7228836Fix()
597 #ifdef BUILDING_ON_LEOPARD
598 NSBundle* coreVideoFrameworkBundle = [NSBundle bundleWithPath:@"/System/Library/Frameworks/CoreVideo.framework"];
599 double version = [[coreVideoFrameworkBundle objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey] doubleValue];
600 return (version >= 48);
605 static bool shouldEnableLoadDeferring()
607 return !applicationIsAdobeInstaller();
610 - (void)_dispatchPendingLoadRequests
612 cache()->loader()->servePendingRequests();
615 - (void)_registerDraggedTypes
617 NSArray *editableTypes = [WebHTMLView _insertablePasteboardTypes];
618 NSArray *URLTypes = [NSPasteboard _web_dragTypesForURL];
619 NSMutableSet *types = [[NSMutableSet alloc] initWithArray:editableTypes];
620 [types addObjectsFromArray:URLTypes];
621 [self registerForDraggedTypes:[types allObjects]];
625 - (BOOL)_usesDocumentViews
627 return _private->usesDocumentViews;
630 - (void)_commonInitializationWithFrameName:(NSString *)frameName groupName:(NSString *)groupName usesDocumentViews:(BOOL)usesDocumentViews
632 WebCoreThreadViolationCheckRoundTwo();
635 WTF::RefCountedLeakCounter::suppressMessages(webViewIsOpen);
638 WebPreferences *standardPreferences = [WebPreferences standardPreferences];
639 [standardPreferences willAddToWebView];
641 _private->preferences = [standardPreferences retain];
642 _private->catchesDelegateExceptions = YES;
643 _private->mainFrameDocumentReady = NO;
644 _private->drawsBackground = YES;
645 _private->backgroundColor = [[NSColor colorWithDeviceWhite:1 alpha:1] retain];
646 _private->usesDocumentViews = usesDocumentViews;
647 _private->includesFlattenedCompositingLayersWhenDrawingToBitmap = YES;
649 WebFrameView *frameView = nil;
650 if (_private->usesDocumentViews) {
651 NSRect f = [self frame];
652 frameView = [[WebFrameView alloc] initWithFrame: NSMakeRect(0,0,f.size.width,f.size.height)];
653 [frameView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
654 [self addSubview:frameView];
658 static bool didOneTimeInitialization = false;
659 if (!didOneTimeInitialization) {
660 WebKitInitializeLoggingChannelsIfNecessary();
661 WebCore::InitializeLoggingChannelsIfNecessary();
662 [WebHistoryItem initWindowWatcherIfNecessary];
664 WebKitInitializeDatabasesIfNecessary();
666 WebKitInitializeApplicationCachePathIfNecessary();
667 patchMailRemoveAttributesMethod();
669 // Initialize our platform strategies.
670 WebPlatformStrategies::initialize();
672 didOneTimeInitialization = true;
675 Page::PageClients pageClients;
676 pageClients.chromeClient = new WebChromeClient(self);
677 pageClients.contextMenuClient = new WebContextMenuClient(self);
678 pageClients.editorClient = new WebEditorClient(self);
679 pageClients.dragClient = new WebDragClient(self);
680 pageClients.inspectorClient = new WebInspectorClient(self);
681 pageClients.pluginHalterClient = new WebPluginHalterClient(self);
682 #if ENABLE(CLIENT_BASED_GEOLOCATION)
683 pageClients.geolocationControllerClient = new WebGeolocationControllerClient(self);
685 _private->page = new Page(pageClients);
687 _private->page->setCanStartMedia([self window]);
688 _private->page->settings()->setLocalStorageDatabasePath([[self preferences] _localStorageDatabasePath]);
690 [WebFrame _createMainFrameWithPage:_private->page frameName:frameName frameView:frameView];
692 #ifndef BUILDING_ON_TIGER
693 NSRunLoop *runLoop = [NSRunLoop mainRunLoop];
695 NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
698 if (WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_LOADING_DURING_COMMON_RUNLOOP_MODES))
699 [self scheduleInRunLoop:runLoop forMode:(NSString *)kCFRunLoopCommonModes];
701 [self scheduleInRunLoop:runLoop forMode:NSDefaultRunLoopMode];
703 [self _addToAllWebViewsSet];
704 [self setGroupName:groupName];
706 // If there's already a next key view (e.g., from a nib), wire it up to our
707 // contained frame view. In any case, wire our next key view up to the our
708 // contained frame view. This works together with our becomeFirstResponder
709 // and setNextKeyView overrides.
710 NSView *nextKeyView = [self nextKeyView];
711 if (nextKeyView && nextKeyView != frameView)
712 [frameView setNextKeyView:nextKeyView];
713 [super setNextKeyView:frameView];
715 if ([[self class] shouldIncludeInWebKitStatistics])
718 [self _registerDraggedTypes];
720 WebPreferences *prefs = [self preferences];
721 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:)
722 name:WebPreferencesChangedNotification object:prefs];
724 // Post a notification so the WebCore settings update.
725 [[self preferences] _postPreferencesChangesNotification];
727 if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_LOCAL_RESOURCE_SECURITY_RESTRICTION)) {
728 // Originally, we allowed all local loads.
729 SecurityOrigin::setLocalLoadPolicy(SecurityOrigin::AllowLocalLoadsForAll);
730 } else if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_MORE_STRICT_LOCAL_RESOURCE_SECURITY_RESTRICTION)) {
731 // Later, we allowed local loads for local URLs and documents loaded
732 // with substitute data.
733 SecurityOrigin::setLocalLoadPolicy(SecurityOrigin::AllowLocalLoadsForLocalAndSubstituteData);
736 if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_CONTENT_SNIFFING_FOR_FILE_URLS))
737 ResourceHandle::forceContentSniffing();
739 #if ENABLE(VIDEO) && USE(GSTREAMER)
740 [self _scheduleGlibContextIterations];
745 - (id)_initWithFrame:(NSRect)f frameName:(NSString *)frameName groupName:(NSString *)groupName usesDocumentViews:(BOOL)usesDocumentViews
747 self = [super initWithFrame:f];
751 #ifdef ENABLE_WEBKIT_UNSET_DYLD_FRAMEWORK_PATH
752 // DYLD_FRAMEWORK_PATH is used so Safari will load the development version of WebKit, which
753 // may not work with other WebKit applications. Unsetting DYLD_FRAMEWORK_PATH removes the
754 // need for Safari to unset it to prevent it from being passed to applications it launches.
755 // Unsetting it when a WebView is first created is as good a place as any.
756 // See <http://bugs.webkit.org/show_bug.cgi?id=4286> for more details.
757 if (getenv("WEBKIT_UNSET_DYLD_FRAMEWORK_PATH")) {
758 unsetenv("DYLD_FRAMEWORK_PATH");
759 unsetenv("WEBKIT_UNSET_DYLD_FRAMEWORK_PATH");
763 _private = [[WebViewPrivate alloc] init];
764 [self _commonInitializationWithFrameName:frameName groupName:groupName usesDocumentViews:usesDocumentViews];
765 [self setMaintainsBackForwardList: YES];
769 - (BOOL)_mustDrawUnionedRect:(NSRect)rect singleRects:(const NSRect *)rects count:(NSInteger)count
771 // If count == 0 here, use the rect passed in for drawing. This is a workaround for:
772 // <rdar://problem/3908282> REGRESSION (Mail): No drag image dragging selected text in Blot and Mail
773 // The reason for the workaround is that this method is called explicitly from the code
774 // to generate a drag image, and at that time, getRectsBeingDrawn:count: will return a zero count.
775 const int cRectThreshold = 10;
776 const float cWastedSpaceThreshold = 0.75f;
777 BOOL useUnionedRect = (count <= 1) || (count > cRectThreshold);
778 if (!useUnionedRect) {
779 // Attempt to guess whether or not we should use the unioned rect or the individual rects.
780 // We do this by computing the percentage of "wasted space" in the union. If that wasted space
781 // is too large, then we will do individual rect painting instead.
782 float unionPixels = (rect.size.width * rect.size.height);
783 float singlePixels = 0;
784 for (int i = 0; i < count; ++i)
785 singlePixels += rects[i].size.width * rects[i].size.height;
786 float wastedSpace = 1 - (singlePixels / unionPixels);
787 if (wastedSpace <= cWastedSpaceThreshold)
788 useUnionedRect = YES;
790 return useUnionedRect;
793 - (void)drawSingleRect:(NSRect)rect
795 ASSERT(!_private->usesDocumentViews);
797 [NSGraphicsContext saveGraphicsState];
801 [[self mainFrame] _drawRect:rect contentsOnly:NO];
803 [[self _UIDelegateForwarder] webView:self didDrawRect:rect];
805 if (WebNodeHighlight *currentHighlight = [self currentNodeHighlight])
806 [currentHighlight setNeedsUpdateInTargetViewRect:rect];
808 [NSGraphicsContext restoreGraphicsState];
809 } @catch (NSException *localException) {
810 [NSGraphicsContext restoreGraphicsState];
811 LOG_ERROR("Exception caught while drawing: %@", localException);
812 [localException raise];
818 return _private && !_private->usesDocumentViews;
821 - (void)setFrameSize:(NSSize)size
823 if (!_private->usesDocumentViews && !NSEqualSizes(_private->lastLayoutSize, size)) {
824 Frame* frame = [self _mainCoreFrame];
825 // FIXME: Viewless WebKit is broken with Safari banners (e.g., the Find banner). We'll have to figure out a way for
826 // Safari to communicate that this space is being consumed. For WebKit with document views, there's no
827 // need to do an explicit resize, since WebFrameViews have auto resizing turned on and will handle changing
828 // their bounds automatically. See <rdar://problem/6835573> for details.
829 frame->view()->resize(IntSize(size));
830 frame->view()->setNeedsLayout();
831 [self setNeedsDisplay:YES];
832 _private->lastLayoutSize = size;
835 [super setFrameSize:size];
838 #if USE(ACCELERATED_COMPOSITING) || !defined(BUILDING_ON_TIGER)
840 - (void)_viewWillDrawInternal
842 Frame* frame = [self _mainCoreFrame];
843 if (frame && frame->view())
844 frame->view()->layoutIfNeededRecursive();
849 #ifndef BUILDING_ON_TIGER
853 if (!_private->usesDocumentViews)
854 [self _viewWillDrawInternal];
855 [super viewWillDraw];
861 - (void)drawRect:(NSRect)rect
863 if (_private->usesDocumentViews)
864 return [super drawRect:rect];
866 ASSERT_MAIN_THREAD();
870 [self getRectsBeingDrawn:&rects count:&count];
873 if ([self _mustDrawUnionedRect:rect singleRects:rects count:count])
874 [self drawSingleRect:rect];
876 for (int i = 0; i < count; ++i)
877 [self drawSingleRect:rects[i]];
880 + (NSArray *)_supportedMIMETypes
882 // Load the plug-in DB allowing plug-ins to install types.
883 [WebPluginDatabase sharedDatabase];
884 return [[WebFrameView _viewTypesAllowImageTypeOmission:NO] allKeys];
887 + (NSArray *)_supportedFileExtensions
889 NSMutableSet *extensions = [[NSMutableSet alloc] init];
890 NSArray *MIMETypes = [self _supportedMIMETypes];
891 NSEnumerator *enumerator = [MIMETypes objectEnumerator];
893 while ((MIMEType = [enumerator nextObject]) != nil) {
894 NSArray *extensionsForType = WKGetExtensionsForMIMEType(MIMEType);
895 if (extensionsForType) {
896 [extensions addObjectsFromArray:extensionsForType];
899 NSArray *uniqueExtensions = [extensions allObjects];
900 [extensions release];
901 return uniqueExtensions;
904 static NSMutableSet *knownPluginMIMETypes()
906 static NSMutableSet *mimeTypes = [[NSMutableSet alloc] init];
911 + (void)_registerPluginMIMEType:(NSString *)MIMEType
913 [WebView registerViewClass:[WebHTMLView class] representationClass:[WebHTMLRepresentation class] forMIMEType:MIMEType];
914 [knownPluginMIMETypes() addObject:MIMEType];
917 + (void)_unregisterPluginMIMEType:(NSString *)MIMEType
919 [self _unregisterViewClassAndRepresentationClassForMIMEType:MIMEType];
920 [knownPluginMIMETypes() removeObject:MIMEType];
923 + (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType allowingPlugins:(BOOL)allowPlugins
925 MIMEType = [MIMEType lowercaseString];
926 Class viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:YES] _webkit_objectForMIMEType:MIMEType];
927 Class repClass = [[WebDataSource _repTypesAllowImageTypeOmission:YES] _webkit_objectForMIMEType:MIMEType];
929 if (!viewClass || !repClass || [[WebPDFView supportedMIMETypes] containsObject:MIMEType]) {
930 // Our optimization to avoid loading the plug-in DB and image types for the HTML case failed.
933 // Load the plug-in DB allowing plug-ins to install types.
934 [WebPluginDatabase sharedDatabase];
937 // Load the image types and get the view class and rep class. This should be the fullest picture of all handled types.
938 viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:NO] _webkit_objectForMIMEType:MIMEType];
939 repClass = [[WebDataSource _repTypesAllowImageTypeOmission:NO] _webkit_objectForMIMEType:MIMEType];
942 if (viewClass && repClass) {
943 if (viewClass == [WebHTMLView class] && repClass == [WebHTMLRepresentation class]) {
944 // Special-case WebHTMLView for text types that shouldn't be shown.
945 if ([[WebHTMLView unsupportedTextMIMETypes] containsObject:MIMEType])
948 // If the MIME type is a known plug-in we might not want to load it.
949 if (!allowPlugins && [knownPluginMIMETypes() containsObject:MIMEType]) {
950 BOOL isSupportedByWebKit = [[WebHTMLView supportedNonImageMIMETypes] containsObject:MIMEType] ||
951 [[WebHTMLView supportedMIMETypes] containsObject:MIMEType];
953 // If this is a known plug-in MIME type and WebKit can't show it natively, we don't want to show it.
954 if (!isSupportedByWebKit)
968 - (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType
970 if ([[self class] _viewClass:vClass andRepresentationClass:rClass forMIMEType:MIMEType allowingPlugins:[_private->preferences arePlugInsEnabled]])
973 if (_private->pluginDatabase) {
974 WebBasePluginPackage *pluginPackage = [_private->pluginDatabase pluginForMIMEType:MIMEType];
977 *vClass = [WebHTMLView class];
979 *rClass = [WebHTMLRepresentation class];
987 + (void)_setAlwaysUseATSU:(BOOL)f
989 [self _setAlwaysUsesComplexTextCodePath:f];
992 + (void)_setAlwaysUsesComplexTextCodePath:(BOOL)f
994 Font::setCodePath(f ? Font::Complex : Font::Auto);
997 + (BOOL)canCloseAllWebViews
999 return DOMWindow::dispatchAllPendingBeforeUnloadEvents();
1002 + (void)closeAllWebViews
1004 DOMWindow::dispatchAllPendingUnloadEvents();
1006 // This will close the WebViews in a random order. Change this if close order is important.
1007 // Make a new set to avoid mutating the set we are enumerating.
1008 NSSet *webViewsToClose = [NSSet setWithSet:(NSSet *)allWebViewsSet];
1009 NSEnumerator *enumerator = [webViewsToClose objectEnumerator];
1010 while (WebView *webView = [enumerator nextObject])
1014 + (BOOL)canShowFile:(NSString *)path
1016 return [[self class] canShowMIMEType:[WebView _MIMETypeForFile:path]];
1019 + (NSString *)suggestedFileExtensionForMIMEType:(NSString *)type
1021 return WKGetPreferredExtensionForMIMEType(type);
1026 return !_private || _private->closed;
1029 - (void)_closePluginDatabases
1031 pluginDatabaseClientCount--;
1033 // Close both sets of plug-in databases because plug-ins need an opportunity to clean up files, etc.
1035 // Unload the WebView local plug-in database.
1036 if (_private->pluginDatabase) {
1037 [_private->pluginDatabase destroyAllPluginInstanceViews];
1038 [_private->pluginDatabase close];
1039 [_private->pluginDatabase release];
1040 _private->pluginDatabase = nil;
1043 // Keep the global plug-in database active until the app terminates to avoid having to reload plug-in bundles.
1044 if (!pluginDatabaseClientCount && applicationIsTerminating)
1045 [WebPluginDatabase closeSharedDatabase];
1048 - (void)_closeWithFastTeardown
1051 WTF::RefCountedLeakCounter::suppressMessages("At least one WebView was closed with fast teardown.");
1054 [[NSDistributedNotificationCenter defaultCenter] removeObserver:self];
1055 [[NSNotificationCenter defaultCenter] removeObserver:self];
1057 [self _closePluginDatabases];
1060 static bool fastDocumentTeardownEnabled()
1063 static bool enabled = ![[NSUserDefaults standardUserDefaults] boolForKey:WebKitEnableFullDocumentTeardownPreferenceKey];
1065 static bool initialized = false;
1066 static bool enabled = false;
1068 // This allows debug builds to default to not have fast teardown, so leak checking still works.
1069 // But still allow the WebKitEnableFullDocumentTeardown default to override it if present.
1070 NSNumber *setting = [[NSUserDefaults standardUserDefaults] objectForKey:WebKitEnableFullDocumentTeardownPreferenceKey];
1072 enabled = ![setting boolValue];
1079 // _close is here only for backward compatibility; clients and subclasses should use
1080 // public method -close instead.
1083 if (!_private || _private->closed)
1086 _private->closed = YES;
1087 [self _removeFromAllWebViewsSet];
1089 [self _closingEventHandling];
1092 WTF::RefCountedLeakCounter::cancelMessageSuppression(webViewIsOpen);
1095 // To quit the apps fast we skip document teardown, except plugins
1096 // need to be destroyed and unloaded.
1097 if (applicationIsTerminating && fastDocumentTeardownEnabled()) {
1098 [self _closeWithFastTeardown];
1103 [self _exitFullscreen];
1106 if (Frame* mainFrame = [self _mainCoreFrame])
1107 mainFrame->loader()->detachFromParent();
1109 [self setHostWindow:nil];
1111 [self setDownloadDelegate:nil];
1112 [self setEditingDelegate:nil];
1113 [self setFrameLoadDelegate:nil];
1114 [self setPolicyDelegate:nil];
1115 [self setResourceLoadDelegate:nil];
1116 [self setScriptDebugDelegate:nil];
1117 [self setUIDelegate:nil];
1119 [_private->inspector webViewClosed];
1121 // To avoid leaks, call removeDragCaret in case it wasn't called after moveDragCaretToPoint.
1122 [self removeDragCaret];
1124 // Deleteing the WebCore::Page will clear the page cache so we call destroy on
1125 // all the plug-ins in the page cache to break any retain cycles.
1126 // See comment in HistoryItem::releaseAllPendingPageCaches() for more information.
1127 Page* page = _private->page;
1131 if (_private->hasSpellCheckerDocumentTag) {
1132 [[NSSpellChecker sharedSpellChecker] closeSpellDocumentWithTag:_private->spellCheckerDocumentTag];
1133 _private->hasSpellCheckerDocumentTag = NO;
1136 #if USE(ACCELERATED_COMPOSITING)
1137 [self _clearLayerSyncLoopObserver];
1140 #if ENABLE(VIDEO) && USE(GSTREAMER)
1141 [self _clearGlibLoopObserver];
1144 [[NSDistributedNotificationCenter defaultCenter] removeObserver:self];
1145 [[NSNotificationCenter defaultCenter] removeObserver:self];
1147 [WebPreferences _removeReferenceForIdentifier:[self preferencesIdentifier]];
1149 WebPreferences *preferences = _private->preferences;
1150 _private->preferences = nil;
1151 [preferences didRemoveFromWebView];
1152 [preferences release];
1154 [self _closePluginDatabases];
1157 // Need this to make leak messages accurate.
1158 if (applicationIsTerminating) {
1159 gcController().garbageCollectNow();
1160 [WebCache setDisabled:YES];
1165 // Indicates if the WebView is in the midst of a user gesture.
1166 - (BOOL)_isProcessingUserGesture
1168 WebFrame *frame = [self mainFrame];
1169 return core(frame)->loader()->isProcessingUserGesture();
1172 + (NSString *)_MIMETypeForFile:(NSString *)path
1174 NSString *extension = [path pathExtension];
1175 NSString *MIMEType = nil;
1177 // Get the MIME type from the extension.
1178 if ([extension length] != 0) {
1179 MIMEType = WKGetMIMETypeForExtension(extension);
1182 // If we can't get a known MIME type from the extension, sniff.
1183 if ([MIMEType length] == 0 || [MIMEType isEqualToString:@"application/octet-stream"]) {
1184 NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:path];
1185 NSData *data = [handle readDataOfLength:WEB_GUESS_MIME_TYPE_PEEK_LENGTH];
1187 if ([data length] != 0) {
1188 MIMEType = [data _webkit_guessedMIMEType];
1190 if ([MIMEType length] == 0) {
1191 MIMEType = @"application/octet-stream";
1198 - (WebDownload *)_downloadURL:(NSURL *)URL
1202 NSURLRequest *request = [[NSURLRequest alloc] initWithURL:URL];
1203 WebDownload *download = [WebDownload _downloadWithRequest:request
1204 delegate:_private->downloadDelegate
1211 - (WebView *)_openNewWindowWithRequest:(NSURLRequest *)request
1213 NSDictionary *features = [[NSDictionary alloc] init];
1214 WebView *newWindowWebView = [[self _UIDelegateForwarder] webView:self
1215 createWebViewWithRequest:nil
1216 windowFeatures:features];
1218 if (!newWindowWebView)
1221 CallUIDelegate(newWindowWebView, @selector(webViewShow:));
1222 return newWindowWebView;
1225 - (WebInspector *)inspector
1227 if (!_private->inspector)
1228 _private->inspector = [[WebInspector alloc] initWithWebView:self];
1229 return _private->inspector;
1232 - (WebCore::Page*)page
1234 return _private->page;
1237 - (NSMenu *)_menuForElement:(NSDictionary *)element defaultItems:(NSArray *)items
1239 NSArray *defaultMenuItems = [[WebDefaultUIDelegate sharedUIDelegate] webView:self contextMenuItemsForElement:element defaultMenuItems:items];
1241 NSArray *menuItems = CallUIDelegate(self, @selector(webView:contextMenuItemsForElement:defaultMenuItems:), element, defaultMenuItems);
1245 unsigned count = [menuItems count];
1249 NSMenu *menu = [[NSMenu alloc] init];
1250 for (unsigned i = 0; i < count; i++)
1251 [menu addItem:[menuItems objectAtIndex:i]];
1253 return [menu autorelease];
1256 - (void)_mouseDidMoveOverElement:(NSDictionary *)dictionary modifierFlags:(NSUInteger)modifierFlags
1258 // We originally intended to call this delegate method sometimes with a nil dictionary, but due to
1259 // a bug dating back to WebKit 1.0 this delegate was never called with nil! Unfortunately we can't
1260 // start calling this with nil since it will break Adobe Help Viewer, and possibly other clients.
1263 CallUIDelegate(self, @selector(webView:mouseDidMoveOverElement:modifierFlags:), dictionary, modifierFlags);
1266 - (void)_loadBackForwardListFromOtherView:(WebView *)otherView
1268 if (!_private->page)
1271 if (!otherView->_private->page)
1274 // It turns out the right combination of behavior is done with the back/forward load
1275 // type. (See behavior matrix at the top of WebFramePrivate.) So we copy all the items
1276 // in the back forward list, and go to the current one.
1278 BackForwardList* backForwardList = _private->page->backForwardList();
1279 ASSERT(!backForwardList->currentItem()); // destination list should be empty
1281 BackForwardList* otherBackForwardList = otherView->_private->page->backForwardList();
1282 if (!otherBackForwardList->currentItem())
1283 return; // empty back forward list, bail
1285 HistoryItem* newItemToGoTo = 0;
1287 int lastItemIndex = otherBackForwardList->forwardListCount();
1288 for (int i = -otherBackForwardList->backListCount(); i <= lastItemIndex; ++i) {
1290 // If this item is showing , save away its current scroll and form state,
1291 // since that might have changed since loading and it is normally not saved
1292 // until we leave that page.
1293 otherView->_private->page->mainFrame()->loader()->history()->saveDocumentAndScrollState();
1295 RefPtr<HistoryItem> newItem = otherBackForwardList->itemAtIndex(i)->copy();
1297 newItemToGoTo = newItem.get();
1298 backForwardList->addItem(newItem.release());
1301 ASSERT(newItemToGoTo);
1302 _private->page->goToItem(newItemToGoTo, FrameLoadTypeIndexedBackForward);
1305 - (void)_setFormDelegate: (id<WebFormDelegate>)delegate
1307 _private->formDelegate = delegate;
1310 - (id<WebFormDelegate>)_formDelegate
1312 return _private->formDelegate;
1315 - (BOOL)_needsAdobeFrameReloadingQuirk
1317 static BOOL needsQuirk = WKAppVersionCheckLessThan(@"com.adobe.Acrobat", -1, 9.0)
1318 || WKAppVersionCheckLessThan(@"com.adobe.Acrobat.Pro", -1, 9.0)
1319 || WKAppVersionCheckLessThan(@"com.adobe.Reader", -1, 9.0)
1320 || WKAppVersionCheckLessThan(@"com.adobe.distiller", -1, 9.0)
1321 || WKAppVersionCheckLessThan(@"com.adobe.Contribute", -1, 4.2)
1322 || WKAppVersionCheckLessThan(@"com.adobe.dreamweaver-9.0", -1, 9.1)
1323 || WKAppVersionCheckLessThan(@"com.macromedia.fireworks", -1, 9.1)
1324 || WKAppVersionCheckLessThan(@"com.adobe.InCopy", -1, 5.1)
1325 || WKAppVersionCheckLessThan(@"com.adobe.InDesign", -1, 5.1)
1326 || WKAppVersionCheckLessThan(@"com.adobe.Soundbooth", -1, 2);
1331 - (BOOL)_needsLinkElementTextCSSQuirk
1333 static BOOL needsQuirk = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_LINK_ELEMENT_TEXT_CSS_QUIRK)
1334 && WKAppVersionCheckLessThan(@"com.e-frontier.shade10", -1, 10.6);
1338 - (BOOL)_needsKeyboardEventDisambiguationQuirks
1340 static BOOL needsQuirks = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_IE_COMPATIBLE_KEYBOARD_EVENT_DISPATCH) && !applicationIsSafari();
1344 - (BOOL)_needsFrameLoadDelegateRetainQuirk
1346 static BOOL needsQuirk = WKAppVersionCheckLessThan(@"com.equinux.iSale5", -1, 5.6);
1350 - (void)_preferencesChangedNotification:(NSNotification *)notification
1352 WebPreferences *preferences = (WebPreferences *)[notification object];
1353 ASSERT(preferences == [self preferences]);
1355 if (!_private->userAgentOverridden)
1356 _private->userAgent = String();
1358 // Cache this value so we don't have to read NSUserDefaults on each page load
1359 _private->useSiteSpecificSpoofing = [preferences _useSiteSpecificSpoofing];
1361 // Update corresponding WebCore Settings object.
1362 if (!_private->page)
1365 Settings* settings = _private->page->settings();
1367 settings->setCursiveFontFamily([preferences cursiveFontFamily]);
1368 settings->setDefaultFixedFontSize([preferences defaultFixedFontSize]);
1369 settings->setDefaultFontSize([preferences defaultFontSize]);
1370 settings->setDefaultTextEncodingName([preferences defaultTextEncodingName]);
1371 settings->setUsesEncodingDetector([preferences usesEncodingDetector]);
1372 settings->setFantasyFontFamily([preferences fantasyFontFamily]);
1373 settings->setFixedFontFamily([preferences fixedFontFamily]);
1374 settings->setForceFTPDirectoryListings([preferences _forceFTPDirectoryListings]);
1375 settings->setFTPDirectoryTemplatePath([preferences _ftpDirectoryTemplatePath]);
1376 settings->setLocalStorageDatabasePath([preferences _localStorageDatabasePath]);
1377 settings->setJavaEnabled([preferences isJavaEnabled]);
1378 settings->setJavaScriptEnabled([preferences isJavaScriptEnabled]);
1379 settings->setWebSecurityEnabled([preferences isWebSecurityEnabled]);
1380 settings->setAllowUniversalAccessFromFileURLs([preferences allowUniversalAccessFromFileURLs]);
1381 settings->setAllowFileAccessFromFileURLs([preferences allowFileAccessFromFileURLs]);
1382 settings->setJavaScriptCanOpenWindowsAutomatically([preferences javaScriptCanOpenWindowsAutomatically]);
1383 settings->setMinimumFontSize([preferences minimumFontSize]);
1384 settings->setMinimumLogicalFontSize([preferences minimumLogicalFontSize]);
1385 settings->setPluginsEnabled([preferences arePlugInsEnabled]);
1386 #if ENABLE(DATABASE)
1387 AbstractDatabase::setIsAvailable([preferences databasesEnabled]);
1389 settings->setLocalStorageEnabled([preferences localStorageEnabled]);
1390 settings->setExperimentalNotificationsEnabled([preferences experimentalNotificationsEnabled]);
1391 settings->setPrivateBrowsingEnabled([preferences privateBrowsingEnabled]);
1392 settings->setSansSerifFontFamily([preferences sansSerifFontFamily]);
1393 settings->setSerifFontFamily([preferences serifFontFamily]);
1394 settings->setStandardFontFamily([preferences standardFontFamily]);
1395 settings->setLoadsImagesAutomatically([preferences loadsImagesAutomatically]);
1396 settings->setShouldPrintBackgrounds([preferences shouldPrintBackgrounds]);
1397 settings->setTextAreasAreResizable([preferences textAreasAreResizable]);
1398 settings->setShrinksStandaloneImagesToFit([preferences shrinksStandaloneImagesToFit]);
1399 settings->setEditableLinkBehavior(core([preferences editableLinkBehavior]));
1400 settings->setEditingBehaviorType(core([preferences editingBehavior]));
1401 settings->setTextDirectionSubmenuInclusionBehavior(core([preferences textDirectionSubmenuInclusionBehavior]));
1402 settings->setDOMPasteAllowed([preferences isDOMPasteAllowed]);
1403 settings->setUsesPageCache([self usesPageCache]);
1404 settings->setShowsURLsInToolTips([preferences showsURLsInToolTips]);
1405 settings->setDeveloperExtrasEnabled([preferences developerExtrasEnabled]);
1406 settings->setAuthorAndUserStylesEnabled([preferences authorAndUserStylesEnabled]);
1407 settings->setApplicationChromeMode([preferences applicationChromeModeEnabled]);
1408 if ([preferences userStyleSheetEnabled]) {
1409 NSString* location = [[preferences userStyleSheetLocation] _web_originalDataAsString];
1410 if ([location isEqualToString:@"apple-dashboard://stylesheet"])
1411 location = @"file:///System/Library/PrivateFrameworks/DashboardClient.framework/Resources/widget.css";
1412 settings->setUserStyleSheetLocation([NSURL URLWithString:(location ? location : @"")]);
1414 settings->setUserStyleSheetLocation([NSURL URLWithString:@""]);
1415 settings->setNeedsAdobeFrameReloadingQuirk([self _needsAdobeFrameReloadingQuirk]);
1416 settings->setTreatsAnyTextCSSLinkAsStylesheet([self _needsLinkElementTextCSSQuirk]);
1417 settings->setNeedsKeyboardEventDisambiguationQuirks([self _needsKeyboardEventDisambiguationQuirks]);
1418 settings->setNeedsLeopardMailQuirks(runningLeopardMail());
1419 settings->setNeedsTigerMailQuirks(runningTigerMail());
1420 settings->setNeedsSiteSpecificQuirks(_private->useSiteSpecificSpoofing);
1421 settings->setWebArchiveDebugModeEnabled([preferences webArchiveDebugModeEnabled]);
1422 settings->setLocalFileContentSniffingEnabled([preferences localFileContentSniffingEnabled]);
1423 settings->setOfflineWebApplicationCacheEnabled([preferences offlineWebApplicationCacheEnabled]);
1424 settings->setZoomMode([preferences zoomsTextOnly] ? ZoomTextOnly : ZoomPage);
1425 settings->setJavaScriptCanAccessClipboard([preferences javaScriptCanAccessClipboard]);
1426 settings->setXSSAuditorEnabled([preferences isXSSAuditorEnabled]);
1427 settings->setEnforceCSSMIMETypeInStrictMode(!WKAppVersionCheckLessThan(@"com.apple.iWeb", -1, 2.1));
1428 settings->setDNSPrefetchingEnabled([preferences isDNSPrefetchingEnabled]);
1430 // FIXME: Enabling accelerated compositing when WebGL is enabled causes tests to fail on Leopard which expect HW compositing to be disabled.
1431 // Until we fix that, I will comment out the test (CFM)
1432 settings->setAcceleratedCompositingEnabled((coreVideoHas7228836Fix() || [preferences webGLEnabled]) && [preferences acceleratedCompositingEnabled]);
1433 settings->setShowDebugBorders([preferences showDebugBorders]);
1434 settings->setShowRepaintCounter([preferences showRepaintCounter]);
1435 settings->setPluginAllowedRunTime([preferences pluginAllowedRunTime]);
1436 settings->setWebGLEnabled([preferences webGLEnabled]);
1437 settings->setLoadDeferringEnabled(shouldEnableLoadDeferring());
1438 settings->setFrameFlatteningEnabled([preferences isFrameFlatteningEnabled]);
1439 settings->setHTML5ParserEnabled([preferences html5ParserEnabled]);
1440 settings->setHTML5TreeBuilderEnabled_DO_NOT_USE([preferences html5TreeBuilderEnabled]);
1441 settings->setPaginateDuringLayoutEnabled([preferences paginateDuringLayoutEnabled]);
1442 settings->setMemoryInfoEnabled([preferences memoryInfoEnabled]);
1445 static inline IMP getMethod(id o, SEL s)
1447 return [o respondsToSelector:s] ? [o methodForSelector:s] : 0;
1450 - (void)_cacheResourceLoadDelegateImplementations
1452 WebResourceDelegateImplementationCache *cache = &_private->resourceLoadDelegateImplementations;
1453 id delegate = _private->resourceProgressDelegate;
1456 bzero(cache, sizeof(WebResourceDelegateImplementationCache));
1460 cache->didCancelAuthenticationChallengeFunc = getMethod(delegate, @selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:));
1461 cache->didFailLoadingWithErrorFromDataSourceFunc = getMethod(delegate, @selector(webView:resource:didFailLoadingWithError:fromDataSource:));
1462 cache->didFinishLoadingFromDataSourceFunc = getMethod(delegate, @selector(webView:resource:didFinishLoadingFromDataSource:));
1463 cache->didLoadResourceFromMemoryCacheFunc = getMethod(delegate, @selector(webView:didLoadResourceFromMemoryCache:response:length:fromDataSource:));
1464 cache->didReceiveAuthenticationChallengeFunc = getMethod(delegate, @selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:));
1465 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
1466 cache->canAuthenticateAgainstProtectionSpaceFunc = getMethod(delegate, @selector(webView:resource:canAuthenticateAgainstProtectionSpace:forDataSource:));
1468 cache->didReceiveContentLengthFunc = getMethod(delegate, @selector(webView:resource:didReceiveContentLength:fromDataSource:));
1469 cache->didReceiveResponseFunc = getMethod(delegate, @selector(webView:resource:didReceiveResponse:fromDataSource:));
1470 cache->identifierForRequestFunc = getMethod(delegate, @selector(webView:identifierForInitialRequest:fromDataSource:));
1471 cache->plugInFailedWithErrorFunc = getMethod(delegate, @selector(webView:plugInFailedWithError:dataSource:));
1472 cache->willCacheResponseFunc = getMethod(delegate, @selector(webView:resource:willCacheResponse:fromDataSource:));
1473 cache->willSendRequestFunc = getMethod(delegate, @selector(webView:resource:willSendRequest:redirectResponse:fromDataSource:));
1474 cache->shouldUseCredentialStorageFunc = getMethod(delegate, @selector(webView:resource:shouldUseCredentialStorageForDataSource:));
1477 - (void)_cacheFrameLoadDelegateImplementations
1479 WebFrameLoadDelegateImplementationCache *cache = &_private->frameLoadDelegateImplementations;
1480 id delegate = _private->frameLoadDelegate;
1483 bzero(cache, sizeof(WebFrameLoadDelegateImplementationCache));
1487 cache->didCancelClientRedirectForFrameFunc = getMethod(delegate, @selector(webView:didCancelClientRedirectForFrame:));
1488 cache->didChangeLocationWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didChangeLocationWithinPageForFrame:));
1489 cache->didPushStateWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didPushStateWithinPageForFrame:));
1490 cache->didReplaceStateWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didReplaceStateWithinPageForFrame:));
1491 cache->didPopStateWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didPopStateWithinPageForFrame:));
1492 cache->didClearWindowObjectForFrameFunc = getMethod(delegate, @selector(webView:didClearWindowObject:forFrame:));
1493 cache->didClearWindowObjectForFrameInScriptWorldFunc = getMethod(delegate, @selector(webView:didClearWindowObjectForFrame:inScriptWorld:));
1494 cache->didClearInspectorWindowObjectForFrameFunc = getMethod(delegate, @selector(webView:didClearInspectorWindowObject:forFrame:));
1495 cache->didCommitLoadForFrameFunc = getMethod(delegate, @selector(webView:didCommitLoadForFrame:));
1496 cache->didFailLoadWithErrorForFrameFunc = getMethod(delegate, @selector(webView:didFailLoadWithError:forFrame:));
1497 cache->didFailProvisionalLoadWithErrorForFrameFunc = getMethod(delegate, @selector(webView:didFailProvisionalLoadWithError:forFrame:));
1498 cache->didFinishDocumentLoadForFrameFunc = getMethod(delegate, @selector(webView:didFinishDocumentLoadForFrame:));
1499 cache->didFinishLoadForFrameFunc = getMethod(delegate, @selector(webView:didFinishLoadForFrame:));
1500 cache->didFirstLayoutInFrameFunc = getMethod(delegate, @selector(webView:didFirstLayoutInFrame:));
1501 cache->didFirstVisuallyNonEmptyLayoutInFrameFunc = getMethod(delegate, @selector(webView:didFirstVisuallyNonEmptyLayoutInFrame:));
1502 cache->didHandleOnloadEventsForFrameFunc = getMethod(delegate, @selector(webView:didHandleOnloadEventsForFrame:));
1503 cache->didReceiveIconForFrameFunc = getMethod(delegate, @selector(webView:didReceiveIcon:forFrame:));
1504 cache->didReceiveServerRedirectForProvisionalLoadForFrameFunc = getMethod(delegate, @selector(webView:didReceiveServerRedirectForProvisionalLoadForFrame:));
1505 cache->didReceiveTitleForFrameFunc = getMethod(delegate, @selector(webView:didReceiveTitle:forFrame:));
1506 cache->didStartProvisionalLoadForFrameFunc = getMethod(delegate, @selector(webView:didStartProvisionalLoadForFrame:));
1507 cache->willCloseFrameFunc = getMethod(delegate, @selector(webView:willCloseFrame:));
1508 cache->willPerformClientRedirectToURLDelayFireDateForFrameFunc = getMethod(delegate, @selector(webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:));
1509 cache->windowScriptObjectAvailableFunc = getMethod(delegate, @selector(webView:windowScriptObjectAvailable:));
1510 cache->didDisplayInsecureContentFunc = getMethod(delegate, @selector(webViewDidDisplayInsecureContent:));
1511 cache->didRunInsecureContentFunc = getMethod(delegate, @selector(webView:didRunInsecureContent:));
1514 - (void)_cacheScriptDebugDelegateImplementations
1516 WebScriptDebugDelegateImplementationCache *cache = &_private->scriptDebugDelegateImplementations;
1517 id delegate = _private->scriptDebugDelegate;
1520 bzero(cache, sizeof(WebScriptDebugDelegateImplementationCache));
1524 cache->didParseSourceFunc = getMethod(delegate, @selector(webView:didParseSource:baseLineNumber:fromURL:sourceId:forWebFrame:));
1525 if (cache->didParseSourceFunc)
1526 cache->didParseSourceExpectsBaseLineNumber = YES;
1528 cache->didParseSourceFunc = getMethod(delegate, @selector(webView:didParseSource:fromURL:sourceId:forWebFrame:));
1530 cache->failedToParseSourceFunc = getMethod(delegate, @selector(webView:failedToParseSource:baseLineNumber:fromURL:withError:forWebFrame:));
1531 cache->didEnterCallFrameFunc = getMethod(delegate, @selector(webView:didEnterCallFrame:sourceId:line:forWebFrame:));
1532 cache->willExecuteStatementFunc = getMethod(delegate, @selector(webView:willExecuteStatement:sourceId:line:forWebFrame:));
1533 cache->willLeaveCallFrameFunc = getMethod(delegate, @selector(webView:willLeaveCallFrame:sourceId:line:forWebFrame:));
1534 cache->exceptionWasRaisedFunc = getMethod(delegate, @selector(webView:exceptionWasRaised:sourceId:line:forWebFrame:));
1537 - (void)_cacheHistoryDelegateImplementations
1539 WebHistoryDelegateImplementationCache *cache = &_private->historyDelegateImplementations;
1540 id delegate = _private->historyDelegate;
1543 bzero(cache, sizeof(WebHistoryDelegateImplementationCache));
1547 cache->navigatedFunc = getMethod(delegate, @selector(webView:didNavigateWithNavigationData:inFrame:));
1548 cache->clientRedirectFunc = getMethod(delegate, @selector(webView:didPerformClientRedirectFromURL:toURL:inFrame:));
1549 cache->serverRedirectFunc = getMethod(delegate, @selector(webView:didPerformServerRedirectFromURL:toURL:inFrame:));
1550 cache->setTitleFunc = getMethod(delegate, @selector(webView:updateHistoryTitle:forURL:));
1551 cache->populateVisitedLinksFunc = getMethod(delegate, @selector(populateVisitedLinksForWebView:));
1554 - (id)_policyDelegateForwarder
1556 if (!_private->policyDelegateForwarder)
1557 _private->policyDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->policyDelegate defaultTarget:[WebDefaultPolicyDelegate sharedPolicyDelegate] catchExceptions:_private->catchesDelegateExceptions];
1558 return _private->policyDelegateForwarder;
1561 - (id)_UIDelegateForwarder
1563 if (!_private->UIDelegateForwarder)
1564 _private->UIDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->UIDelegate defaultTarget:[WebDefaultUIDelegate sharedUIDelegate] catchExceptions:_private->catchesDelegateExceptions];
1565 return _private->UIDelegateForwarder;
1568 - (id)_editingDelegateForwarder
1570 // This can be called during window deallocation by QTMovieView in the QuickTime Cocoa Plug-in.
1571 // Not sure if that is a bug or not.
1575 if (!_private->editingDelegateForwarder)
1576 _private->editingDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->editingDelegate defaultTarget:[WebDefaultEditingDelegate sharedEditingDelegate] catchExceptions:_private->catchesDelegateExceptions];
1577 return _private->editingDelegateForwarder;
1580 - (void)_closeWindow
1582 [[self _UIDelegateForwarder] webViewClose:self];
1585 + (void)_unregisterViewClassAndRepresentationClassForMIMEType:(NSString *)MIMEType
1587 [[WebFrameView _viewTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType];
1588 [[WebDataSource _repTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType];
1590 // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
1591 // in the WebCore MIMEType registry. For now we're doing this in a safe, limited manner
1592 // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
1593 MIMETypeRegistry::getSupportedNonImageMIMETypes().remove(MIMEType);
1596 + (void)_registerViewClass:(Class)viewClass representationClass:(Class)representationClass forURLScheme:(NSString *)URLScheme
1598 NSString *MIMEType = [self _generatedMIMETypeForURLScheme:URLScheme];
1599 [self registerViewClass:viewClass representationClass:representationClass forMIMEType:MIMEType];
1601 // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
1602 // in the WebCore MIMEType registry. For now we're doing this in a safe, limited manner
1603 // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
1604 if ([viewClass class] == [WebHTMLView class])
1605 MIMETypeRegistry::getSupportedNonImageMIMETypes().add(MIMEType);
1607 // This is used to make _representationExistsForURLScheme faster.
1608 // Without this set, we'd have to create the MIME type each time.
1609 if (schemesWithRepresentationsSet == nil) {
1610 schemesWithRepresentationsSet = [[NSMutableSet alloc] init];
1612 [schemesWithRepresentationsSet addObject:[[[URLScheme lowercaseString] copy] autorelease]];
1615 + (NSString *)_generatedMIMETypeForURLScheme:(NSString *)URLScheme
1617 return [@"x-apple-web-kit/" stringByAppendingString:[URLScheme lowercaseString]];
1620 + (BOOL)_representationExistsForURLScheme:(NSString *)URLScheme
1622 return [schemesWithRepresentationsSet containsObject:[URLScheme lowercaseString]];
1625 + (BOOL)_canHandleRequest:(NSURLRequest *)request forMainFrame:(BOOL)forMainFrame
1627 // FIXME: If <rdar://problem/5217309> gets fixed, this check can be removed.
1631 if ([NSURLConnection canHandleRequest:request])
1634 NSString *scheme = [[request URL] scheme];
1636 // Representations for URL schemes work at the top level.
1637 if (forMainFrame && [self _representationExistsForURLScheme:scheme])
1640 return [scheme _webkit_isCaseInsensitiveEqualToString:@"applewebdata"];
1643 + (BOOL)_canHandleRequest:(NSURLRequest *)request
1645 return [self _canHandleRequest:request forMainFrame:YES];
1648 + (NSString *)_decodeData:(NSData *)data
1650 HTMLNames::init(); // this method is used for importing bookmarks at startup, so HTMLNames are likely to be uninitialized yet
1651 RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("text/html"); // bookmark files are HTML
1652 String result = decoder->decode(static_cast<const char*>([data bytes]), [data length]);
1653 result += decoder->flush();
1657 - (void)_pushPerformingProgrammaticFocus
1659 _private->programmaticFocusCount++;
1662 - (void)_popPerformingProgrammaticFocus
1664 _private->programmaticFocusCount--;
1667 - (BOOL)_isPerformingProgrammaticFocus
1669 return _private->programmaticFocusCount != 0;
1672 - (void)_didChangeValueForKey: (NSString *)key
1674 LOG (Bindings, "calling didChangeValueForKey: %@", key);
1675 [self didChangeValueForKey: key];
1678 - (void)_willChangeValueForKey: (NSString *)key
1680 LOG (Bindings, "calling willChangeValueForKey: %@", key);
1681 [self willChangeValueForKey: key];
1684 + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key {
1685 static NSSet *manualNotifyKeys = nil;
1686 if (!manualNotifyKeys)
1687 manualNotifyKeys = [[NSSet alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey,
1688 _WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, _WebMainFrameDocumentKey,
1690 if ([manualNotifyKeys containsObject:key])
1695 - (NSArray *)_declaredKeys {
1696 static NSArray *declaredKeys = nil;
1698 declaredKeys = [[NSArray alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey,
1699 _WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, _WebMainFrameDocumentKey, nil];
1700 return declaredKeys;
1703 - (void)setObservationInfo:(void *)info
1705 _private->observationInfo = info;
1708 - (void *)observationInfo
1710 return _private->observationInfo;
1713 - (void)_willChangeBackForwardKeys
1715 [self _willChangeValueForKey: _WebCanGoBackKey];
1716 [self _willChangeValueForKey: _WebCanGoForwardKey];
1719 - (void)_didChangeBackForwardKeys
1721 [self _didChangeValueForKey: _WebCanGoBackKey];
1722 [self _didChangeValueForKey: _WebCanGoForwardKey];
1725 - (void)_didStartProvisionalLoadForFrame:(WebFrame *)frame
1727 [self _willChangeBackForwardKeys];
1728 if (frame == [self mainFrame]){
1729 // Force an observer update by sending a will/did.
1730 [self _willChangeValueForKey: _WebIsLoadingKey];
1731 [self _didChangeValueForKey: _WebIsLoadingKey];
1733 [self _willChangeValueForKey: _WebMainFrameURLKey];
1736 [NSApp setWindowsNeedUpdate:YES];
1739 - (void)_didCommitLoadForFrame:(WebFrame *)frame
1741 if (frame == [self mainFrame])
1742 [self _didChangeValueForKey: _WebMainFrameURLKey];
1743 [NSApp setWindowsNeedUpdate:YES];
1746 - (void)_didFinishLoadForFrame:(WebFrame *)frame
1748 [self _didChangeBackForwardKeys];
1749 if (frame == [self mainFrame]){
1750 // Force an observer update by sending a will/did.
1751 [self _willChangeValueForKey: _WebIsLoadingKey];
1752 [self _didChangeValueForKey: _WebIsLoadingKey];
1754 [NSApp setWindowsNeedUpdate:YES];
1757 - (void)_didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
1759 [self _didChangeBackForwardKeys];
1760 if (frame == [self mainFrame]){
1761 // Force an observer update by sending a will/did.
1762 [self _willChangeValueForKey: _WebIsLoadingKey];
1763 [self _didChangeValueForKey: _WebIsLoadingKey];
1765 [NSApp setWindowsNeedUpdate:YES];
1768 - (void)_didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
1770 [self _didChangeBackForwardKeys];
1771 if (frame == [self mainFrame]){
1772 // Force an observer update by sending a will/did.
1773 [self _willChangeValueForKey: _WebIsLoadingKey];
1774 [self _didChangeValueForKey: _WebIsLoadingKey];
1776 [self _didChangeValueForKey: _WebMainFrameURLKey];
1778 [NSApp setWindowsNeedUpdate:YES];
1781 - (NSCachedURLResponse *)_cachedResponseForURL:(NSURL *)URL
1783 NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:URL];
1784 [request _web_setHTTPUserAgent:[self userAgentForURL:URL]];
1785 NSCachedURLResponse *cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:request];
1787 return cachedResponse;
1790 - (void)_writeImageForElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
1792 NSURL *linkURL = [element objectForKey:WebElementLinkURLKey];
1793 DOMElement *domElement = [element objectForKey:WebElementDOMNodeKey];
1794 [pasteboard _web_writeImage:(NSImage *)(domElement ? nil : [element objectForKey:WebElementImageKey])
1796 URL:linkURL ? linkURL : (NSURL *)[element objectForKey:WebElementImageURLKey]
1797 title:[element objectForKey:WebElementImageAltStringKey]
1798 archive:[[element objectForKey:WebElementDOMNodeKey] webArchive]
1803 - (void)_writeLinkElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
1805 [pasteboard _web_writeURL:[element objectForKey:WebElementLinkURLKey]
1806 andTitle:[element objectForKey:WebElementLinkLabelKey]
1810 - (void)_setInitiatedDrag:(BOOL)initiatedDrag
1812 if (!_private->page)
1814 _private->page->dragController()->setDidInitiateDrag(initiatedDrag);
1817 #if ENABLE(DASHBOARD_SUPPORT)
1819 #define DASHBOARD_CONTROL_LABEL @"control"
1821 - (void)_addControlRect:(NSRect)bounds clip:(NSRect)clip fromView:(NSView *)view toDashboardRegions:(NSMutableDictionary *)regions
1823 NSRect adjustedBounds = bounds;
1824 adjustedBounds.origin = [self convertPoint:bounds.origin fromView:view];
1825 adjustedBounds.origin.y = [self bounds].size.height - adjustedBounds.origin.y;
1826 adjustedBounds.size = bounds.size;
1828 NSRect adjustedClip;
1829 adjustedClip.origin = [self convertPoint:clip.origin fromView:view];
1830 adjustedClip.origin.y = [self bounds].size.height - adjustedClip.origin.y;
1831 adjustedClip.size = clip.size;
1833 WebDashboardRegion *region = [[WebDashboardRegion alloc] initWithRect:adjustedBounds
1834 clip:adjustedClip type:WebDashboardRegionTypeScrollerRectangle];
1835 NSMutableArray *scrollerRegions = [regions objectForKey:DASHBOARD_CONTROL_LABEL];
1836 if (!scrollerRegions) {
1837 scrollerRegions = [[NSMutableArray alloc] init];
1838 [regions setObject:scrollerRegions forKey:DASHBOARD_CONTROL_LABEL];
1839 [scrollerRegions release];
1841 [scrollerRegions addObject:region];
1845 - (void)_addScrollerDashboardRegionsForFrameView:(FrameView*)frameView dashboardRegions:(NSMutableDictionary *)regions
1847 NSView *documentView = [[kit(frameView->frame()) frameView] documentView];
1849 const HashSet<RefPtr<Widget> >* children = frameView->children();
1850 HashSet<RefPtr<Widget> >::const_iterator end = children->end();
1851 for (HashSet<RefPtr<Widget> >::const_iterator it = children->begin(); it != end; ++it) {
1852 Widget* widget = (*it).get();
1853 if (widget->isFrameView()) {
1854 [self _addScrollerDashboardRegionsForFrameView:static_cast<FrameView*>(widget) dashboardRegions:regions];
1858 if (!widget->isScrollbar())
1861 // FIXME: This should really pass an appropriate clip, but our first try got it wrong, and
1862 // it's not common to need this to be correct in Dashboard widgets.
1863 NSRect bounds = widget->frameRect();
1864 [self _addControlRect:bounds clip:bounds fromView:documentView toDashboardRegions:regions];
1868 - (void)_addScrollerDashboardRegions:(NSMutableDictionary *)regions from:(NSArray *)views
1870 // Add scroller regions for NSScroller and WebCore scrollbars
1871 NSUInteger count = [views count];
1872 for (NSUInteger i = 0; i < count; i++) {
1873 NSView *view = [views objectAtIndex:i];
1875 if ([view isKindOfClass:[WebHTMLView class]]) {
1876 if (Frame* coreFrame = core([(WebHTMLView*)view _frame])) {
1877 if (FrameView* coreView = coreFrame->view())
1878 [self _addScrollerDashboardRegionsForFrameView:coreView dashboardRegions:regions];
1880 } else if ([view isKindOfClass:[NSScroller class]]) {
1881 // AppKit places absent scrollers at -100,-100
1882 if ([view frame].origin.y < 0)
1884 [self _addControlRect:[view bounds] clip:[view visibleRect] fromView:view toDashboardRegions:regions];
1886 [self _addScrollerDashboardRegions:regions from:[view subviews]];
1890 - (void)_addScrollerDashboardRegions:(NSMutableDictionary *)regions
1892 [self _addScrollerDashboardRegions:regions from:[self subviews]];
1895 - (NSDictionary *)_dashboardRegions
1897 // Only return regions from main frame.
1898 Frame* mainFrame = [self _mainCoreFrame];
1901 NSMutableDictionary *regions = mainFrame->dashboardRegionsDictionary();
1902 [self _addScrollerDashboardRegions:regions];
1906 - (void)_setDashboardBehavior:(WebDashboardBehavior)behavior to:(BOOL)flag
1908 // FIXME: Remove this blanket assignment once Dashboard and Dashcode implement
1909 // specific support for the backward compatibility mode flag.
1910 if (behavior == WebDashboardBehaviorAllowWheelScrolling && flag == NO && _private->page)
1911 _private->page->settings()->setUsesDashboardBackwardCompatibilityMode(true);
1914 case WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows: {
1915 _private->dashboardBehaviorAlwaysSendMouseEventsToAllWindows = flag;
1918 case WebDashboardBehaviorAlwaysSendActiveNullEventsToPlugIns: {
1919 _private->dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns = flag;
1922 case WebDashboardBehaviorAlwaysAcceptsFirstMouse: {
1923 _private->dashboardBehaviorAlwaysAcceptsFirstMouse = flag;
1926 case WebDashboardBehaviorAllowWheelScrolling: {
1927 _private->dashboardBehaviorAllowWheelScrolling = flag;
1930 case WebDashboardBehaviorUseBackwardCompatibilityMode: {
1932 _private->page->settings()->setUsesDashboardBackwardCompatibilityMode(flag);
1938 - (BOOL)_dashboardBehavior:(WebDashboardBehavior)behavior
1941 case WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows: {
1942 return _private->dashboardBehaviorAlwaysSendMouseEventsToAllWindows;
1944 case WebDashboardBehaviorAlwaysSendActiveNullEventsToPlugIns: {
1945 return _private->dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns;
1947 case WebDashboardBehaviorAlwaysAcceptsFirstMouse: {
1948 return _private->dashboardBehaviorAlwaysAcceptsFirstMouse;
1950 case WebDashboardBehaviorAllowWheelScrolling: {
1951 return _private->dashboardBehaviorAllowWheelScrolling;
1953 case WebDashboardBehaviorUseBackwardCompatibilityMode: {
1954 return _private->page && _private->page->settings()->usesDashboardBackwardCompatibilityMode();
1960 #endif /* ENABLE(DASHBOARD_SUPPORT) */
1962 + (void)_setShouldUseFontSmoothing:(BOOL)f
1964 Font::setShouldUseSmoothing(f);
1967 + (BOOL)_shouldUseFontSmoothing
1969 return Font::shouldUseSmoothing();
1972 + (void)_setUsesTestModeFocusRingColor:(BOOL)f
1974 setUsesTestModeFocusRingColor(f);
1977 + (BOOL)_usesTestModeFocusRingColor
1979 return usesTestModeFocusRingColor();
1982 - (void)setAlwaysShowVerticalScroller:(BOOL)flag
1984 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
1986 [scrollview setVerticalScrollingMode:ScrollbarAlwaysOn andLock:YES];
1988 [scrollview setVerticalScrollingModeLocked:NO];
1989 [scrollview setVerticalScrollingMode:ScrollbarAuto andLock:NO];
1993 - (BOOL)alwaysShowVerticalScroller
1995 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
1996 return [scrollview verticalScrollingModeLocked] && [scrollview verticalScrollingMode] == ScrollbarAlwaysOn;
1999 - (void)setAlwaysShowHorizontalScroller:(BOOL)flag
2001 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
2003 [scrollview setHorizontalScrollingMode:ScrollbarAlwaysOn andLock:YES];
2005 [scrollview setHorizontalScrollingModeLocked:NO];
2006 [scrollview setHorizontalScrollingMode:ScrollbarAuto andLock:NO];
2010 - (void)setProhibitsMainFrameScrolling:(BOOL)prohibits
2012 if (Frame* mainFrame = [self _mainCoreFrame])
2013 mainFrame->view()->setProhibitsScrolling(prohibits);
2016 - (BOOL)alwaysShowHorizontalScroller
2018 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
2019 return [scrollview horizontalScrollingModeLocked] && [scrollview horizontalScrollingMode] == ScrollbarAlwaysOn;
2022 - (void)_setInViewSourceMode:(BOOL)flag
2024 if (Frame* mainFrame = [self _mainCoreFrame])
2025 mainFrame->setInViewSourceMode(flag);
2028 - (BOOL)_inViewSourceMode
2030 Frame* mainFrame = [self _mainCoreFrame];
2031 return mainFrame && mainFrame->inViewSourceMode();
2034 - (void)_setUseFastImageScalingMode:(BOOL)flag
2036 if (_private->page && _private->page->inLowQualityImageInterpolationMode() != flag) {
2037 _private->page->setInLowQualityImageInterpolationMode(flag);
2038 [self setNeedsDisplay:YES];
2042 - (BOOL)_inFastImageScalingMode
2045 return _private->page->inLowQualityImageInterpolationMode();
2049 - (BOOL)_cookieEnabled
2052 return _private->page->cookieEnabled();
2056 - (void)_setCookieEnabled:(BOOL)enable
2059 _private->page->setCookieEnabled(enable);
2062 - (void)_setAdditionalWebPlugInPaths:(NSArray *)newPaths
2064 if (!_private->pluginDatabase)
2065 _private->pluginDatabase = [[WebPluginDatabase alloc] init];
2067 [_private->pluginDatabase setPlugInPaths:newPaths];
2068 [_private->pluginDatabase refresh];
2071 - (void)_attachScriptDebuggerToAllFrames
2073 for (Frame* frame = [self _mainCoreFrame]; frame; frame = frame->tree()->traverseNext())
2074 [kit(frame) _attachScriptDebugger];
2077 - (void)_detachScriptDebuggerFromAllFrames
2079 for (Frame* frame = [self _mainCoreFrame]; frame; frame = frame->tree()->traverseNext())
2080 [kit(frame) _detachScriptDebugger];
2083 - (void)setBackgroundColor:(NSColor *)backgroundColor
2085 if ([_private->backgroundColor isEqual:backgroundColor])
2088 id old = _private->backgroundColor;
2089 _private->backgroundColor = [backgroundColor retain];
2092 [[self mainFrame] _updateBackgroundAndUpdatesWhileOffscreen];
2095 - (NSColor *)backgroundColor
2097 return _private->backgroundColor;
2100 - (BOOL)defersCallbacks
2102 if (!_private->page)
2104 return _private->page->defersLoading();
2107 - (void)setDefersCallbacks:(BOOL)defer
2109 if (!_private->page)
2111 return _private->page->setDefersLoading(defer);
2114 // For backwards compatibility with the WebBackForwardList API, we honor both
2115 // a per-WebView and a per-preferences setting for whether to use the page cache.
2117 - (BOOL)usesPageCache
2119 return _private->usesPageCache && [[self preferences] usesPageCache];
2122 - (void)setUsesPageCache:(BOOL)usesPageCache
2124 _private->usesPageCache = usesPageCache;
2126 // Post a notification so the WebCore settings update.
2127 [[self preferences] _postPreferencesChangesNotification];
2130 - (WebHistoryItem *)_globalHistoryItem
2132 if (!_private->page)
2134 return kit(_private->page->globalHistoryItem());
2137 - (WebTextIterator *)textIteratorForRect:(NSRect)rect
2139 IntPoint rectStart(rect.origin.x, rect.origin.y);
2140 IntPoint rectEnd(rect.origin.x + rect.size.width, rect.origin.y + rect.size.height);
2142 Frame* coreFrame = [self _mainCoreFrame];
2146 VisibleSelection selectionInsideRect(coreFrame->visiblePositionForPoint(rectStart), coreFrame->visiblePositionForPoint(rectEnd));
2148 return [[[WebTextIterator alloc] initWithRange:kit(selectionInsideRect.toNormalizedRange().get())] autorelease];
2151 - (void)handleAuthenticationForResource:(id)identifier challenge:(NSURLAuthenticationChallenge *)challenge fromDataSource:(WebDataSource *)dataSource
2153 NSWindow *window = [self hostWindow] ? [self hostWindow] : [self window];
2154 [[WebPanelAuthenticationHandler sharedHandler] startAuthentication:challenge window:window];
2157 - (void)_clearUndoRedoOperations
2159 if (!_private->page)
2161 _private->page->clearUndoRedoOperations();
2164 - (void)_setCatchesDelegateExceptions:(BOOL)f
2166 _private->catchesDelegateExceptions = f;
2169 - (BOOL)_catchesDelegateExceptions
2171 return _private->catchesDelegateExceptions;
2174 - (void)_executeCoreCommandByName:(NSString *)name value:(NSString *)value
2176 Frame* coreFrame = [self _mainCoreFrame];
2179 coreFrame->editor()->command(name).execute(value);
2182 - (void)_setCustomHTMLTokenizerTimeDelay:(double)timeDelay
2184 if (!_private->page)
2186 return _private->page->setCustomHTMLTokenizerTimeDelay(timeDelay);
2189 - (void)_setCustomHTMLTokenizerChunkSize:(int)chunkSize
2191 if (!_private->page)
2193 return _private->page->setCustomHTMLTokenizerChunkSize(chunkSize);
2196 - (void)_clearMainFrameName
2198 _private->page->mainFrame()->tree()->clearName();
2201 - (void)setSelectTrailingWhitespaceEnabled:(BOOL)flag
2203 _private->selectTrailingWhitespaceEnabled = flag;
2205 [self setSmartInsertDeleteEnabled:false];
2208 - (BOOL)isSelectTrailingWhitespaceEnabled
2210 return _private->selectTrailingWhitespaceEnabled;
2213 - (void)setMemoryCacheDelegateCallsEnabled:(BOOL)enabled
2215 _private->page->setMemoryCacheClientCallsEnabled(enabled);
2218 - (BOOL)areMemoryCacheDelegateCallsEnabled
2220 return _private->page->areMemoryCacheClientCallsEnabled();
2223 - (void)_setJavaScriptURLsAreAllowed:(BOOL)areAllowed
2225 _private->page->setJavaScriptURLsAreAllowed(areAllowed);
2228 + (NSCursor *)_pointingHandCursor
2230 return handCursor().platformCursor();
2233 - (BOOL)_postsAcceleratedCompositingNotifications
2235 #if USE(ACCELERATED_COMPOSITING)
2236 return _private->postsAcceleratedCompositingNotifications;
2242 - (void)_setPostsAcceleratedCompositingNotifications:(BOOL)flag
2244 #if USE(ACCELERATED_COMPOSITING)
2245 _private->postsAcceleratedCompositingNotifications = flag;
2249 - (BOOL)_isUsingAcceleratedCompositing
2251 #if USE(ACCELERATED_COMPOSITING)
2252 if (_private->usesDocumentViews) {
2253 Frame* coreFrame = [self _mainCoreFrame];
2254 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
2255 NSView *documentView = [[kit(frame) frameView] documentView];
2256 if ([documentView isKindOfClass:[WebHTMLView class]] && [(WebHTMLView *)documentView _isUsingAcceleratedCompositing])
2264 - (BOOL)_isSoftwareRenderable
2266 #if USE(ACCELERATED_COMPOSITING)
2267 if (_private->usesDocumentViews) {
2268 Frame* coreFrame = [self _mainCoreFrame];
2269 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
2270 if (FrameView* view = frame->view()) {
2271 if (!view->isSoftwareRenderable())
2280 - (void)_setIncludesFlattenedCompositingLayersWhenDrawingToBitmap:(BOOL)flag
2282 _private->includesFlattenedCompositingLayersWhenDrawingToBitmap = flag;
2285 - (BOOL)_includesFlattenedCompositingLayersWhenDrawingToBitmap
2287 return _private->includesFlattenedCompositingLayersWhenDrawingToBitmap;
2290 static WebBaseNetscapePluginView *_pluginViewForNode(DOMNode *node)
2295 Node* coreNode = core(node);
2299 RenderObject* renderer = coreNode->renderer();
2300 if (!renderer || !renderer->isWidget())
2303 Widget* widget = toRenderWidget(renderer)->widget();
2304 if (!widget || !widget->platformWidget())
2307 NSView *view = widget->platformWidget();
2308 if (![view isKindOfClass:[WebBaseNetscapePluginView class]])
2311 return (WebBaseNetscapePluginView *)view;
2314 + (BOOL)_isNodeHaltedPlugin:(DOMNode *)node
2316 return [_pluginViewForNode(node) isHalted];
2319 + (BOOL)_hasPluginForNodeBeenHalted:(DOMNode *)node
2321 return [_pluginViewForNode(node) hasBeenHalted];
2323 + (void)_restartHaltedPluginForNode:(DOMNode *)node
2328 [_pluginViewForNode(node) resumeFromHalt];
2331 - (NSPasteboard *)_insertionPasteboard
2333 return _private ? _private->insertionPasteboard : nil;
2336 + (void)_addOriginAccessWhitelistEntryWithSourceOrigin:(NSString *)sourceOrigin destinationProtocol:(NSString *)destinationProtocol destinationHost:(NSString *)destinationHost allowDestinationSubdomains:(BOOL)allowDestinationSubdomains
2338 SecurityOrigin::addOriginAccessWhitelistEntry(*SecurityOrigin::createFromString(sourceOrigin), destinationProtocol, destinationHost, allowDestinationSubdomains);
2341 + (void)_removeOriginAccessWhitelistEntryWithSourceOrigin:(NSString *)sourceOrigin destinationProtocol:(NSString *)destinationProtocol destinationHost:(NSString *)destinationHost allowDestinationSubdomains:(BOOL)allowDestinationSubdomains
2343 SecurityOrigin::removeOriginAccessWhitelistEntry(*SecurityOrigin::createFromString(sourceOrigin), destinationProtocol, destinationHost, allowDestinationSubdomains);
2346 +(void)_resetOriginAccessWhitelists
2348 SecurityOrigin::resetOriginAccessWhitelists();
2351 - (void)_updateActiveState
2353 if (_private && _private->page)
2354 _private->page->focusController()->setActive([[self window] isKeyWindow]);
2357 static PassOwnPtr<Vector<String> > toStringVector(NSArray* patterns)
2359 // Convert the patterns into Vectors.
2360 NSUInteger count = [patterns count];
2363 Vector<String>* patternsVector = new Vector<String>;
2364 for (NSUInteger i = 0; i < count; ++i) {
2365 id entry = [patterns objectAtIndex:i];
2366 if ([entry isKindOfClass:[NSString class]])
2367 patternsVector->append(String((NSString*)entry));
2369 return patternsVector;
2372 + (void)_addUserScriptToGroup:(NSString *)groupName world:(WebScriptWorld *)world source:(NSString *)source url:(NSURL *)url
2373 whitelist:(NSArray *)whitelist blacklist:(NSArray *)blacklist
2374 injectionTime:(WebUserScriptInjectionTime)injectionTime
2376 [WebView _addUserScriptToGroup:groupName world:world source:source url:url whitelist:whitelist blacklist:blacklist injectionTime:injectionTime injectedFrames:WebInjectInAllFrames];
2379 + (void)_addUserScriptToGroup:(NSString *)groupName world:(WebScriptWorld *)world source:(NSString *)source url:(NSURL *)url
2380 whitelist:(NSArray *)whitelist blacklist:(NSArray *)blacklist
2381 injectionTime:(WebUserScriptInjectionTime)injectionTime
2382 injectedFrames:(WebUserContentInjectedFrames)injectedFrames
2384 String group(groupName);
2385 if (group.isEmpty())
2388 PageGroup* pageGroup = PageGroup::pageGroup(group);
2392 pageGroup->addUserScriptToWorld(core(world), source, url, toStringVector(whitelist), toStringVector(blacklist),
2393 injectionTime == WebInjectAtDocumentStart ? InjectAtDocumentStart : InjectAtDocumentEnd,
2394 injectedFrames == WebInjectInAllFrames ? InjectInAllFrames : InjectInTopFrameOnly);
2397 + (void)_addUserStyleSheetToGroup:(NSString *)groupName world:(WebScriptWorld *)world source:(NSString *)source url:(NSURL *)url
2398 whitelist:(NSArray *)whitelist blacklist:(NSArray *)blacklist
2400 [WebView _addUserStyleSheetToGroup:groupName world:world source:source url:url whitelist:whitelist blacklist:blacklist injectedFrames:WebInjectInAllFrames];
2403 + (void)_addUserStyleSheetToGroup:(NSString *)groupName world:(WebScriptWorld *)world source:(NSString *)source url:(NSURL *)url
2404 whitelist:(NSArray *)whitelist blacklist:(NSArray *)blacklist
2405 injectedFrames:(WebUserContentInjectedFrames)injectedFrames
2407 String group(groupName);
2408 if (group.isEmpty())
2411 PageGroup* pageGroup = PageGroup::pageGroup(group);
2415 pageGroup->addUserStyleSheetToWorld(core(world), source, url, toStringVector(whitelist), toStringVector(blacklist), injectedFrames == WebInjectInAllFrames ? InjectInAllFrames : InjectInTopFrameOnly);
2418 + (void)_removeUserScriptFromGroup:(NSString *)groupName world:(WebScriptWorld *)world url:(NSURL *)url
2420 String group(groupName);
2421 if (group.isEmpty())
2424 PageGroup* pageGroup = PageGroup::pageGroup(group);
2428 pageGroup->removeUserScriptFromWorld(core(world), url);
2431 + (void)_removeUserStyleSheetFromGroup:(NSString *)groupName world:(WebScriptWorld *)world url:(NSURL *)url
2433 String group(groupName);
2434 if (group.isEmpty())
2437 PageGroup* pageGroup = PageGroup::pageGroup(group);
2441 pageGroup->removeUserStyleSheetFromWorld(core(world), url);
2444 + (void)_removeUserScriptsFromGroup:(NSString *)groupName world:(WebScriptWorld *)world
2446 String group(groupName);
2447 if (group.isEmpty())
2450 PageGroup* pageGroup = PageGroup::pageGroup(group);
2454 pageGroup->removeUserScriptsFromWorld(core(world));
2457 + (void)_removeUserStyleSheetsFromGroup:(NSString *)groupName world:(WebScriptWorld *)world
2459 String group(groupName);
2460 if (group.isEmpty())
2463 PageGroup* pageGroup = PageGroup::pageGroup(group);
2467 pageGroup->removeUserStyleSheetsFromWorld(core(world));
2470 + (void)_removeAllUserContentFromGroup:(NSString *)groupName
2472 String group(groupName);
2473 if (group.isEmpty())
2476 PageGroup* pageGroup = PageGroup::pageGroup(group);
2480 pageGroup->removeAllUserContent();
2483 - (BOOL)cssAnimationsSuspended
2485 return _private->cssAnimationsSuspended;
2488 - (void)setCSSAnimationsSuspended:(BOOL)suspended
2490 if (suspended == _private->cssAnimationsSuspended)
2493 _private->cssAnimationsSuspended = suspended;
2495 Frame* frame = core([self mainFrame]);
2497 frame->animation()->suspendAnimations(frame->document());
2499 frame->animation()->resumeAnimations(frame->document());
2502 + (void)_setDomainRelaxationForbidden:(BOOL)forbidden forURLScheme:(NSString *)scheme
2504 SecurityOrigin::setDomainRelaxationForbiddenForURLScheme(forbidden, scheme);
2507 + (void)_registerURLSchemeAsSecure:(NSString *)scheme
2509 SchemeRegistry::registerURLSchemeAsSecure(scheme);
2514 @implementation _WebSafeForwarder
2516 // Used to send messages to delegates that implement informal protocols.
2518 - (id)initWithTarget:(id)t defaultTarget:(id)dt catchExceptions:(BOOL)c
2520 self = [super init];
2523 target = t; // Non retained.
2525 catchExceptions = c;
2529 - (void)forwardInvocation:(NSInvocation *)invocation
2531 if ([target respondsToSelector:[invocation selector]]) {
2532 if (catchExceptions) {
2534 [invocation invokeWithTarget:target];
2535 } @catch(id exception) {
2536 ReportDiscardedDelegateException([invocation selector], exception);
2539 [invocation invokeWithTarget:target];
2543 if ([defaultTarget respondsToSelector:[invocation selector]])
2544 [invocation invokeWithTarget:defaultTarget];
2546 // Do nothing quietly if method not implemented.
2549 - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
2551 return [defaultTarget methodSignatureForSelector:aSelector];
2556 @implementation WebView
2560 static BOOL initialized = NO;
2565 InitWebCoreSystemInterface();
2566 JSC::initializeThreading();
2567 WTF::initializeMainThreadToProcessMainThread();
2569 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_applicationWillTerminate) name:NSApplicationWillTerminateNotification object:NSApp];
2570 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:) name:WebPreferencesChangedNotification object:nil];
2571 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesRemovedNotification:) name:WebPreferencesRemovedNotification object:nil];
2573 continuousSpellCheckingEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebContinuousSpellCheckingEnabled];
2574 #ifndef BUILDING_ON_TIGER
2575 grammarCheckingEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebGrammarCheckingEnabled];
2578 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
2579 automaticQuoteSubstitutionEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticQuoteSubstitutionEnabled];
2580 automaticLinkDetectionEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticLinkDetectionEnabled];
2581 automaticDashSubstitutionEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticDashSubstitutionEnabled];
2582 automaticTextReplacementEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticTextReplacementEnabled];
2583 automaticSpellingCorrectionEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticSpellingCorrectionEnabled];
2587 + (void)_applicationWillTerminate
2589 applicationIsTerminating = YES;
2591 if (fastDocumentTeardownEnabled())
2592 [self closeAllWebViews];
2594 if (!pluginDatabaseClientCount)
2595 [WebPluginDatabase closeSharedDatabase];
2597 PageGroup::closeLocalStorage();
2600 + (BOOL)_canShowMIMEType:(NSString *)MIMEType allowingPlugins:(BOOL)allowPlugins
2602 return [self _viewClass:nil andRepresentationClass:nil forMIMEType:MIMEType allowingPlugins:allowPlugins];
2605 + (BOOL)canShowMIMEType:(NSString *)MIMEType
2607 return [self _canShowMIMEType:MIMEType allowingPlugins:YES];
2610 - (BOOL)_canShowMIMEType:(NSString *)MIMEType
2612 return [[self class] _canShowMIMEType:MIMEType allowingPlugins:[_private->preferences arePlugInsEnabled]];
2615 - (WebBasePluginPackage *)_pluginForMIMEType:(NSString *)MIMEType
2617 if (![_private->preferences arePlugInsEnabled])
2620 WebBasePluginPackage *pluginPackage = [[WebPluginDatabase sharedDatabase] pluginForMIMEType:MIMEType];
2622 return pluginPackage;
2624 if (_private->pluginDatabase)
2625 return [_private->pluginDatabase pluginForMIMEType:MIMEType];
2630 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
2631 - (WebBasePluginPackage *)_videoProxyPluginForMIMEType:(NSString *)MIMEType
2633 WebBasePluginPackage *pluginPackage = [[WebPluginDatabase sharedDatabase] pluginForMIMEType:MIMEType];
2635 return pluginPackage;
2637 if (_private->pluginDatabase)
2638 return [_private->pluginDatabase pluginForMIMEType:MIMEType];
2644 - (WebBasePluginPackage *)_pluginForExtension:(NSString *)extension
2646 if (![_private->preferences arePlugInsEnabled])
2649 WebBasePluginPackage *pluginPackage = [[WebPluginDatabase sharedDatabase] pluginForExtension:extension];
2651 return pluginPackage;
2653 if (_private->pluginDatabase)
2654 return [_private->pluginDatabase pluginForExtension:extension];
2659 - (void)addPluginInstanceView:(NSView *)view
2661 if (!_private->pluginDatabase)
2662 _private->pluginDatabase = [[WebPluginDatabase alloc] init];
2663 [_private->pluginDatabase addPluginInstanceView:view];
2666 - (void)removePluginInstanceView:(NSView *)view
2668 if (_private->pluginDatabase)
2669 [_private->pluginDatabase removePluginInstanceView:view];
2672 - (void)removePluginInstanceViewsFor:(WebFrame*)webFrame
2674 if (_private->pluginDatabase)
2675 [_private->pluginDatabase removePluginInstanceViewsFor:webFrame];
2678 - (BOOL)_isMIMETypeRegisteredAsPlugin:(NSString *)MIMEType
2680 if (![_private->preferences arePlugInsEnabled])
2683 if ([[WebPluginDatabase sharedDatabase] isMIMETypeRegistered:MIMEType])
2686 if (_private->pluginDatabase && [_private->pluginDatabase isMIMETypeRegistered:MIMEType])
2692 + (BOOL)canShowMIMETypeAsHTML:(NSString *)MIMEType
2694 return [WebFrameView _canShowMIMETypeAsHTML:MIMEType];
2697 + (NSArray *)MIMETypesShownAsHTML
2699 NSMutableDictionary *viewTypes = [WebFrameView _viewTypesAllowImageTypeOmission:YES];
2700 NSEnumerator *enumerator = [viewTypes keyEnumerator];
2702 NSMutableArray *array = [[[NSMutableArray alloc] init] autorelease];
2704 while ((key = [enumerator nextObject])) {
2705 if ([viewTypes objectForKey:key] == [WebHTMLView class])
2706 [array addObject:key];
2712 + (void)setMIMETypesShownAsHTML:(NSArray *)MIMETypes
2714 NSDictionary *viewTypes = [[WebFrameView _viewTypesAllowImageTypeOmission:YES] copy];
2715 NSEnumerator *enumerator = [viewTypes keyEnumerator];
2717 while ((key = [enumerator nextObject])) {
2718 if ([viewTypes objectForKey:key] == [WebHTMLView class])
2719 [WebView _unregisterViewClassAndRepresentationClassForMIMEType:key];
2722 int i, count = [MIMETypes count];
2723 for (i = 0; i < count; i++) {
2724 [WebView registerViewClass:[WebHTMLView class]
2725 representationClass:[WebHTMLRepresentation class]
2726 forMIMEType:[MIMETypes objectAtIndex:i]];
2728 [viewTypes release];
2731 + (NSURL *)URLFromPasteboard:(NSPasteboard *)pasteboard
2733 return [pasteboard _web_bestURL];
2736 + (NSString *)URLTitleFromPasteboard:(NSPasteboard *)pasteboard
2738 return [pasteboard stringForType:WebURLNamePboardType];
2741 + (void)registerURLSchemeAsLocal:(NSString *)protocol
2743 SchemeRegistry::registerURLSchemeAsLocal(protocol);
2746 - (id)_initWithArguments:(NSDictionary *) arguments
2748 NSCoder *decoder = [arguments objectForKey:@"decoder"];
2750 self = [self initWithCoder:decoder];
2752 ASSERT([arguments objectForKey:@"frame"]);
2753 NSValue *frameValue = [arguments objectForKey:@"frame"];
2754 NSRect frame = (frameValue ? [frameValue rectValue] : NSZeroRect);
2755 NSString *frameName = [arguments objectForKey:@"frameName"];
2756 NSString *groupName = [arguments objectForKey:@"groupName"];
2757 self = [self initWithFrame:frame frameName:frameName groupName:groupName];
2763 static bool clientNeedsWebViewInitThreadWorkaround()
2765 if (WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_WEBVIEW_INIT_THREAD_WORKAROUND))
2768 NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
2771 if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.installer"])
2775 if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.Automator"])
2778 // Automator Runner.
2779 if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.AutomatorRunner"])
2782 // Automator workflows.
2783 if ([bundleIdentifier _webkit_hasCaseInsensitivePrefix:@"com.apple.Automator."])
2786 #if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
2788 if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.Mail"])
2795 static bool needsWebViewInitThreadWorkaround()
2797 static bool isOldClient = clientNeedsWebViewInitThreadWorkaround();
2798 return isOldClient && !pthread_main_np();
2801 - (id)initWithFrame:(NSRect)f
2803 return [self initWithFrame:f frameName:nil groupName:nil];
2806 - (id)initWithFrame:(NSRect)f frameName:(NSString *)frameName groupName:(NSString *)groupName
2808 if (needsWebViewInitThreadWorkaround())
2809 return [[self _webkit_invokeOnMainThread] initWithFrame:f frameName:frameName groupName:groupName];
2811 WebCoreThreadViolationCheckRoundTwo();
2812 return [self _initWithFrame:f frameName:frameName groupName:groupName usesDocumentViews:YES];
2815 - (id)initWithCoder:(NSCoder *)decoder
2817 if (needsWebViewInitThreadWorkaround())
2818 return [[self _webkit_invokeOnMainThread] initWithCoder:decoder];
2820 WebCoreThreadViolationCheckRoundTwo();
2821 WebView *result = nil;
2824 NSString *frameName;
2825 NSString *groupName;
2826 WebPreferences *preferences;
2827 BOOL useBackForwardList = NO;
2828 BOOL allowsUndo = YES;
2830 result = [super initWithCoder:decoder];
2831 result->_private = [[WebViewPrivate alloc] init];
2833 // We don't want any of the archived subviews. The subviews will always
2834 // be created in _commonInitializationFrameName:groupName:.
2835 [[result subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
2837 if ([decoder allowsKeyedCoding]) {
2838 frameName = [decoder decodeObjectForKey:@"FrameName"];
2839 groupName = [decoder decodeObjectForKey:@"GroupName"];
2840 preferences = [decoder decodeObjectForKey:@"Preferences"];
2841 useBackForwardList = [decoder decodeBoolForKey:@"UseBackForwardList"];
2842 if ([decoder containsValueForKey:@"AllowsUndo"])
2843 allowsUndo = [decoder decodeBoolForKey:@"AllowsUndo"];
2846 [decoder decodeValueOfObjCType:@encode(int) at:&version];
2847 frameName = [decoder decodeObject];
2848 groupName = [decoder decodeObject];
2849 preferences = [decoder decodeObject];
2851 [decoder decodeValuesOfObjCTypes:"c", &useBackForwardList];
2852 // The allowsUndo field is no longer written out in encodeWithCoder, but since there are
2853 // version 3 NIBs that have this field encoded, we still need to read it in.
2855 [decoder decodeValuesOfObjCTypes:"c", &allowsUndo];
2858 if (![frameName isKindOfClass:[NSString class]])
2860 if (![groupName isKindOfClass:[NSString class]])
2862 if (![preferences isKindOfClass:[WebPreferences class]])
2865 LOG(Encoding, "FrameName = %@, GroupName = %@, useBackForwardList = %d\n", frameName, groupName, (int)useBackForwardList);
2866 [result _commonInitializationWithFrameName:frameName groupName:groupName usesDocumentViews:YES];
2867 [result page]->backForwardList()->setEnabled(useBackForwardList);
2868 result->_private->allowsUndo = allowsUndo;
2870 [result setPreferences:preferences];
2871 } @catch (NSException *localException) {
2879 - (void)encodeWithCoder:(NSCoder *)encoder
2881 // Set asside the subviews before we archive. We don't want to archive any subviews.
2882 // The subviews will always be created in _commonInitializationFrameName:groupName:.
2883 id originalSubviews = _subviews;
2886 [super encodeWithCoder:encoder];
2888 // Restore the subviews we set aside.
2889 _subviews = originalSubviews;
2891 BOOL useBackForwardList = _private->page && _private->page->backForwardList()->enabled();
2892 if ([encoder allowsKeyedCoding]) {
2893 [encoder encodeObject:[[self mainFrame] name] forKey:@"FrameName"];
2894 [encoder encodeObject:[self groupName] forKey:@"GroupName"];
2895 [encoder encodeObject:[self preferences] forKey:@"Preferences"];
2896 [encoder encodeBool:useBackForwardList forKey:@"UseBackForwardList"];
2897 [encoder encodeBool:_private->allowsUndo forKey:@"AllowsUndo"];
2899 int version = WebViewVersion;
2900 [encoder encodeValueOfObjCType:@encode(int) at:&version];
2901 [encoder encodeObject:[[self mainFrame] name]];
2902 [encoder encodeObject:[self groupName]];
2903 [encoder encodeObject:[self preferences]];
2904 [encoder encodeValuesOfObjCTypes:"c", &useBackForwardList];
2905 // DO NOT encode any new fields here, doing so will break older WebKit releases.
2908 LOG(Encoding, "FrameName = %@, GroupName = %@, useBackForwardList = %d\n", [[self mainFrame] name], [self groupName], (int)useBackForwardList);
2913 if (WebCoreObjCScheduleDeallocateOnMainThread([WebView class], self))
2916 // call close to ensure we tear-down completely
2917 // this maintains our old behavior for existing applications
2920 if ([[self class] shouldIncludeInWebKitStatistics])
2923 if ([self _needsFrameLoadDelegateRetainQuirk])
2924 [_private->frameLoadDelegate release];
2927 // [super dealloc] can end up dispatching against _private (3466082)
2935 ASSERT(_private->closed);
2944 // _close existed first, and some clients might be calling or overriding it, so call through.
2948 - (void)setShouldCloseWithWindow:(BOOL)close
2950 _private->shouldCloseWithWindow = close;
2953 - (BOOL)shouldCloseWithWindow
2955 return _private->shouldCloseWithWindow;
2958 - (void)addWindowObserversForWindow:(NSWindow *)window
2961 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowDidBecomeKey:)
2962 name:NSWindowDidBecomeKeyNotification object:nil];
2963 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowDidResignKey:)
2964 name:NSWindowDidResignKeyNotification object:nil];
2965 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillOrderOnScreen:)
2966 name:WKWindowWillOrderOnScreenNotification() object:window];
2970 - (void)removeWindowObservers
2972 NSWindow *window = [self window];
2974 [[NSNotificationCenter defaultCenter] removeObserver:self
2975 name:NSWindowDidBecomeKeyNotification object:nil];
2976 [[NSNotificationCenter defaultCenter] removeObserver:self
2977 name:NSWindowDidResignKeyNotification object:nil];
2978 [[NSNotificationCenter defaultCenter] removeObserver:self
2979 name:WKWindowWillOrderOnScreenNotification() object:window];
2983 - (void)viewWillMoveToWindow:(NSWindow *)window
2985 // Don't do anything if the WebView isn't initialized.
2986 // This happens when decoding a WebView in a nib.
2987 // FIXME: What sets up the observer of NSWindowWillCloseNotification in this case?
2988 if (!_private || _private->closed)
2991 if ([self window] && [self window] != [self hostWindow])
2992 [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowWillCloseNotification object:[self window]];
2995 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillClose:) name:NSWindowWillCloseNotification object:window];
2997 // Ensure that we will receive the events that WebHTMLView (at least) needs.
2998 // The following are expensive enough that we don't want to call them over
2999 // and over, so do them when we move into a window.
3000 [window setAcceptsMouseMovedEvents:YES];
3001 WKSetNSWindowShouldPostEventNotifications(window, YES);
3003 _private->page->setCanStartMedia(false);
3004 _private->page->willMoveOffscreen();
3007 if (window != [self window]) {
3008 [self removeWindowObservers];
3009 [self addWindowObserversForWindow:window];
3013 - (void)viewDidMoveToWindow
3015 // Don't do anything if we aren't initialized. This happens
3016 // when decoding a WebView. When WebViews are decoded their subviews
3017 // are created by initWithCoder: and so won't be normally
3018 // initialized. The stub views are discarded by WebView.
3019 if (!_private || _private->closed)
3022 if ([self window]) {
3023 _private->page->setCanStartMedia(true);
3024 _private->page->didMoveOnscreen();
3027 [self _updateActiveState];
3030 - (void)_windowDidBecomeKey:(NSNotification *)notification
3032 NSWindow *keyWindow = [notification object];
3033 if (keyWindow == [self window] || keyWindow == [[self window] attachedSheet])
3034 [self _updateActiveState];
3037 - (void)_windowDidResignKey:(NSNotification *)notification
3039 NSWindow *formerKeyWindow = [notification object];
3040 if (formerKeyWindow == [self window] || formerKeyWindow == [[self window] attachedSheet])
3041 [self _updateActiveState];
3044 - (void)_windowWillOrderOnScreen:(NSNotification *)notification
3046 if (![self shouldUpdateWhileOffscreen])
3047 [self setNeedsDisplay:YES];
3050 - (void)_windowWillClose:(NSNotification *)notification
3052 if ([self shouldCloseWithWindow] && ([self window] == [self hostWindow] || ([self window] && ![self hostWindow]) || (![self window] && [self hostWindow])))
3056 - (void)setPreferences:(WebPreferences *)prefs
3059 prefs = [WebPreferences standardPreferences];
3061 if (_private->preferences == prefs)
3064 [prefs willAddToWebView];
3066 WebPreferences *oldPrefs = _private->preferences;
3068 [[NSNotificationCenter defaultCenter] removeObserver:self name:WebPreferencesChangedNotification object:[self preferences]];
3069 [WebPreferences _removeReferenceForIdentifier:[oldPrefs identifier]];
3071 _private->preferences = [prefs retain];
3073 // After registering for the notification, post it so the WebCore settings update.
3074 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:)
3075 name:WebPreferencesChangedNotification object:[self preferences]];
3076 [[self preferences] _postPreferencesChangesNotification];
3078 [oldPrefs didRemoveFromWebView];
3082 - (WebPreferences *)preferences
3084 return _private->preferences;
3087 - (void)setPreferencesIdentifier:(NSString *)anIdentifier
3089 if (!_private->closed && ![anIdentifier isEqual:[[self preferences] identifier]]) {
3090 WebPreferences *prefs = [[WebPreferences alloc] initWithIdentifier:anIdentifier];
3091 [self setPreferences:prefs];
3096 - (NSString *)preferencesIdentifier
3098 return [[self preferences] identifier];
3102 - (void)setUIDelegate:delegate
3104 _private->UIDelegate = delegate;
3105 [_private->UIDelegateForwarder release];
3106 _private->UIDelegateForwarder = nil;
3111 return _private->UIDelegate;
3114 - (void)setResourceLoadDelegate: delegate
3116 _private->resourceProgressDelegate = delegate;
3117 [self _cacheResourceLoadDelegateImplementations];
3120 - (id)resourceLoadDelegate
3122 return _private->resourceProgressDelegate;
3125 - (void)setDownloadDelegate: delegate
3127 _private->downloadDelegate = delegate;
3131 - (id)downloadDelegate
3133 return _private->downloadDelegate;
3136 - (void)setPolicyDelegate:delegate
3138 _private->policyDelegate = delegate;
3139 [_private->policyDelegateForwarder release];
3140 _private->policyDelegateForwarder = nil;
3143 - (id)policyDelegate
3145 return _private->policyDelegate;
3148 - (void)setFrameLoadDelegate:delegate
3150 // <rdar://problem/6950660> - Due to some subtle WebKit changes - presumably to delegate callback behavior - we've
3151 // unconvered a latent bug in at least one WebKit app where the delegate wasn't properly retained by the app and
3152 // was dealloc'ed before being cleared.
3153 // This is an effort to keep such apps working for now.
3154 if ([self _needsFrameLoadDelegateRetainQuirk]) {
3156 [_private->frameLoadDelegate release];
3159 _private->frameLoadDelegate = delegate;
3160 [self _cacheFrameLoadDelegateImplementations];
3162 #if ENABLE(ICONDATABASE)
3163 // If this delegate wants callbacks for icons, fire up the icon database.
3164 if (_private->frameLoadDelegateImplementations.didReceiveIconForFrameFunc)
3165 [WebIconDatabase sharedIconDatabase];
3169 - (id)frameLoadDelegate
3171 return _private->frameLoadDelegate;
3174 - (WebFrame *)mainFrame
3176 // This can be called in initialization, before _private has been set up (3465613)
3177 if (!_private || !_private->page)
3179 return kit(_private->page->mainFrame());
3182 - (WebFrame *)selectedFrame
3184 if (_private->usesDocumentViews) {
3185 // If the first responder is a view in our tree, we get the frame containing the first responder.
3186 // This is faster than searching the frame hierarchy, and will give us a result even in the case
3187 // where the focused frame doesn't actually contain a selection.
3188 WebFrame *focusedFrame = [self _focusedFrame];
3190 return focusedFrame;
3193 // If the first responder is outside of our view tree, we search for a frame containing a selection.
3194 // There should be at most only one of these.
3195 return [[self mainFrame] _findFrameWithSelection];
3198 - (WebBackForwardList *)backForwardList
3200 if (!_private->page)
3202 if (!_private->page->backForwardList()->enabled())
3204 return kit(_private->page->backForwardList());
3207 - (void)setMaintainsBackForwardList:(BOOL)flag
3209 if (!_private->page)
3211 _private->page->backForwardList()->setEnabled(flag);
3216 if (!_private->page)
3219 return _private->page->goBack();
3224 if (!_private->page)
3227 return _private->page->goForward();
3230 - (BOOL)goToBackForwardItem:(WebHistoryItem *)item
3232 if (!_private->page)
3235 _private->page->goToItem(core(item), FrameLoadTypeIndexedBackForward);
3239 - (void)setTextSizeMultiplier:(float)m
3241 [self _setZoomMultiplier:m isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3244 - (float)textSizeMultiplier
3246 return [self _realZoomMultiplierIsTextOnly] ? _private->zoomMultiplier : 1.0f;
3249 - (void)_setZoomMultiplier:(float)multiplier isTextOnly:(BOOL)isTextOnly
3251 // NOTE: This has no visible effect when viewing a PDF (see <rdar://problem/4737380>)
3252 _private->zoomMultiplier = multiplier;
3254 ASSERT(_private->page);
3256 _private->page->settings()->setZoomMode(isTextOnly ? ZoomTextOnly : ZoomPage);
3258 // FIXME: It would be nice to rework this code so that _private->zoomMultiplier doesn't exist
3259 // and instead FrameView::zoomFactor is used.
3260 Frame* coreFrame = [self _mainCoreFrame];
3262 if (FrameView* view = coreFrame->view())
3263 view->setZoomFactor(multiplier, isTextOnly ? ZoomTextOnly : ZoomPage);
3267 - (float)_zoomMultiplier:(BOOL)isTextOnly
3269 if (isTextOnly != [self _realZoomMultiplierIsTextOnly])
3271 return _private->zoomMultiplier;
3274 - (float)_realZoomMultiplier
3276 return _private->zoomMultiplier;
3279 - (BOOL)_realZoomMultiplierIsTextOnly
3281 if (!_private->page)
3284 return _private->page->settings()->zoomMode() == ZoomTextOnly;
3287 #define MinimumZoomMultiplier 0.5f
3288 #define MaximumZoomMultiplier 3.0f
3289 #define ZoomMultiplierRatio 1.2f
3291 - (BOOL)_canZoomOut:(BOOL)isTextOnly
3293 id docView = [[[self mainFrame] frameView] documentView];
3294 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
3295 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
3296 return [zoomingDocView _canZoomOut];
3298 return [self _zoomMultiplier:isTextOnly] / ZoomMultiplierRatio > MinimumZoomMultiplier;
3302 - (BOOL)_canZoomIn:(BOOL)isTextOnly
3304 id docView = [[[self mainFrame] frameView] documentView];
3305 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
3306 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
3307 return [zoomingDocView _canZoomIn];
3309 return [self _zoomMultiplier:isTextOnly] * ZoomMultiplierRatio < MaximumZoomMultiplier;
3312 - (IBAction)_zoomOut:(id)sender isTextOnly:(BOOL)isTextOnly
3314 id docView = [[[self mainFrame] frameView] documentView];
3315 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
3316 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
3317 return [zoomingDocView _zoomOut:sender];
3319 float newScale = [self _zoomMultiplier:isTextOnly] / ZoomMultiplierRatio;
3320 if (newScale > MinimumZoomMultiplier)
3321 [self _setZoomMultiplier:newScale isTextOnly:isTextOnly];
3324 - (IBAction)_zoomIn:(id)sender isTextOnly:(BOOL)isTextOnly
3326 id docView = [[[self mainFrame] frameView] documentView];
3327 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
3328 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
3329 return [zoomingDocView _zoomIn:sender];
3331 float newScale = [self _zoomMultiplier:isTextOnly] * ZoomMultiplierRatio;
3332 if (newScale < MaximumZoomMultiplier)
3333 [self _setZoomMultiplier:newScale isTextOnly:isTextOnly];
3336 - (BOOL)_canResetZoom:(BOOL)isTextOnly
3338 id docView = [[[self mainFrame] frameView] documentView];
3339 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
3340 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
3341 return [zoomingDocView _canResetZoom];
3343 return [self _zoomMultiplier:isTextOnly] != 1.0f;
3346 - (IBAction)_resetZoom:(id)sender isTextOnly:(BOOL)isTextOnly
3348 id docView = [[[self mainFrame] frameView] documentView];
3349 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) {
3350 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView;
3351 return [zoomingDocView _resetZoom:sender];
3353 if ([self _zoomMultiplier:isTextOnly] != 1.0f)
3354 [self _setZoomMultiplier:1.0f isTextOnly:isTextOnly];
3357 - (void)setApplicationNameForUserAgent:(NSString *)applicationName
3359 NSString *name = [applicationName copy];
3360 [_private->applicationNameForUserAgent release];
3361 _private->applicationNameForUserAgent = name;
3362 if (!_private->userAgentOverridden)
3363 _private->userAgent = String();
3366 - (NSString *)applicationNameForUserAgent
3368 return [[_private->applicationNameForUserAgent retain] autorelease];
3371 - (void)setCustomUserAgent:(NSString *)userAgentString
3373 _private->userAgent = userAgentString;
3374 _private->userAgentOverridden = userAgentString != nil;
3377 - (NSString *)customUserAgent
3379 if (!_private->userAgentOverridden)
3381 return _private->userAgent;
3384 - (void)setMediaStyle:(NSString *)mediaStyle
3386 if (_private->mediaStyle != mediaStyle) {
3387 [_private->mediaStyle release];
3388 _private->mediaStyle = [mediaStyle copy];
3392 - (NSString *)mediaStyle
3394 return _private->mediaStyle;
3397 - (BOOL)supportsTextEncoding
3399 id documentView = [[[self mainFrame] frameView] documentView];
3400 return [documentView conformsToProtocol:@protocol(WebDocumentText)]
3401 && [documentView supportsTextEncoding];
3404 - (void)setCustomTextEncodingName:(NSString *)encoding
3406 NSString *oldEncoding = [self customTextEncodingName];
3407 if (encoding == oldEncoding || [encoding isEqualToString:oldEncoding])
3409 if (Frame* mainFrame = [self _mainCoreFrame])
3410 mainFrame->loader()->reloadWithOverrideEncoding(encoding);
3413 - (NSString *)_mainFrameOverrideEncoding
3415 WebDataSource *dataSource = [[self mainFrame] provisionalDataSource];
3416 if (dataSource == nil)
3417 dataSource = [[self mainFrame] _dataSource];
3418 if (dataSource == nil)
3420 return nsStringNilIfEmpty([dataSource _documentLoader]->overrideEncoding());
3423 - (NSString *)customTextEncodingName
3425 return [self _mainFrameOverrideEncoding];
3428 - (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script
3430 // Return statements are only valid in a function but some applications pass in scripts
3431 // prefixed with return (<rdar://problems/5103720&4616860>) since older WebKit versions
3432 // silently ignored the return. If the application is linked against an earlier version
3433 // of WebKit we will strip the return so the script wont fail.
3434 if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_JAVASCRIPT_RETURN_QUIRK)) {
3435 NSRange returnStringRange = [script rangeOfString:@"return "];
3436 if (returnStringRange.length && !returnStringRange.location)
3437 script = [script substringFromIndex:returnStringRange.location + returnStringRange.length];
3440 NSString *result = [[self mainFrame] _stringByEvaluatingJavaScriptFromString:script];
3441 // The only way stringByEvaluatingJavaScriptFromString can return nil is if the frame was removed by the script
3442 // Since there's no way to get rid of the main frame, result will never ever be nil here.
3448 - (WebScriptObject *)windowScriptObject
3450 Frame* coreFrame = [self _mainCoreFrame];
3453 return coreFrame->script()->windowScriptObject();
3456 // Get the appropriate user-agent string for a particular URL.
3457 - (NSString *)userAgentForURL:(NSURL *)url
3459 if (_private->useSiteSpecificSpoofing) {
3460 // No current site-specific spoofs.
3463 if (_private->userAgent.isNull())
3464 _private->userAgent = [[self class] _standardUserAgentWithApplicationName:_private->applicationNameForUserAgent];
3466 return _private->userAgent;
3469 - (void)setHostWindow:(NSWindow *)hostWindow
3471 if (_private->closed && hostWindow)
3473 if (hostWindow == _private->hostWindow)
3476 Frame* coreFrame = [self _mainCoreFrame];
3477 if (_private->usesDocumentViews) {
3478 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
3479 [[[kit(frame) frameView] documentView] viewWillMoveToHostWindow:hostWindow];
3481 if (_private->hostWindow && [self window] != _private->hostWindow)
3482 [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowWillCloseNotification object:_private->hostWindow];
3484 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillClose:) name:NSWindowWillCloseNotification object:hostWindow];
3485 [_private->hostWindow release];
3486 _private->hostWindow = [hostWindow retain];
3487 if (_private->usesDocumentViews) {
3488 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
3489 [[[kit(frame) frameView] documentView] viewDidMoveToHostWindow];
3493 - (NSWindow *)hostWindow
3495 // -[WebView hostWindow] can sometimes be called from the WebView's [super dealloc] method
3496 // so we check here to make sure it's not null.
3500 return _private->hostWindow;
3503 - (NSView <WebDocumentView> *)documentViewAtWindowPoint:(NSPoint)point
3505 return [[self _frameViewAtWindowPoint:point] documentView];
3508 - (NSDictionary *)_elementAtWindowPoint:(NSPoint)windowPoint
3510 WebFrameView *frameView = [self _frameViewAtWindowPoint:windowPoint];
3513 NSView <WebDocumentView> *documentView = [frameView documentView];
3514 if ([documentView conformsToProtocol:@protocol(WebDocumentElement)]) {
3515 NSPoint point = [documentView convertPoint:windowPoint fromView:nil];
3516 return [(NSView <WebDocumentElement> *)documentView elementAtPoint:point];
3518 return [NSDictionary dictionaryWithObject:[frameView webFrame] forKey:WebElementFrameKey];
3521 - (NSDictionary *)elementAtPoint:(NSPoint)point
3523 return [self _elementAtWindowPoint:[self convertPoint:point toView:nil]];
3526 // The following 2 internal NSView methods are called on the drag destination to make scrolling while dragging work.
3527 // Scrolling while dragging will only work if the drag destination is in a scroll view. The WebView is the drag destination.
3528 // When dragging to a WebView, the document subview should scroll, but it doesn't because it is not the drag destination.
3529 // Forward these calls to the document subview to make its scroll view scroll.
3530 - (void)_autoscrollForDraggingInfo:(id)draggingInfo timeDelta:(NSTimeInterval)repeatDelta
3532 NSView <WebDocumentView> *documentView = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3533 [documentView _autoscrollForDraggingInfo:draggingInfo timeDelta:repeatDelta];
3536 - (BOOL)_shouldAutoscrollForDraggingInfo:(id)draggingInfo
3538 NSView <WebDocumentView> *documentView = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3539 return [documentView _shouldAutoscrollForDraggingInfo:draggingInfo];
3542 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)draggingInfo
3544 NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3545 WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]] ? (WebHTMLView*)view : nil);
3546 IntPoint client([draggingInfo draggingLocation]);
3547 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
3548 DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
3549 return core(self)->dragController()->dragEntered(&dragData);
3552 - (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)draggingInfo
3554 Page* page = core(self);
3556 return NSDragOperationNone;
3558 NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3559 WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]] ? (WebHTMLView*)view : nil);
3560 IntPoint client([draggingInfo draggingLocation]);
3561 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
3562 DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
3563 return page->dragController()->dragUpdated(&dragData);
3566 - (void)draggingExited:(id <NSDraggingInfo>)draggingInfo
3568 Page* page = core(self);
3572 NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3573 WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]] ? (WebHTMLView*)view : nil);
3574 IntPoint client([draggingInfo draggingLocation]);
3575 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
3576 DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
3577 page->dragController()->dragExited(&dragData);
3580 - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)draggingInfo
3585 - (BOOL)performDragOperation:(id <NSDraggingInfo>)draggingInfo
3587 NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
3588 WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]]? (WebHTMLView*)view : nil);
3589 IntPoint client([draggingInfo draggingLocation]);
3590 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
3591 DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
3592 return core(self)->dragController()->performDrag(&dragData);
3595 - (NSView *)_hitTest:(NSPoint *)point dragTypes:(NSSet *)types
3597 NSView *hitView = [super _hitTest:point dragTypes:types];
3598 if (!hitView && [[self superview] mouse:*point inRect:[self frame]])
3603 - (BOOL)acceptsFirstResponder
3605 if (_private->usesDocumentViews)
3606 return [[[self mainFrame] frameView] acceptsFirstResponder];
3608 // FIXME (Viewless): Need more code from WebHTMLView here.
3612 - (BOOL)becomeFirstResponder
3614 if (_private->usesDocumentViews) {
3615 if (_private->becomingFirstResponder) {
3616 // Fix for unrepro infinite recursion reported in Radar 4448181. If we hit this assert on
3617 // a debug build, we should figure out what causes the problem and do a better fix.
3618 ASSERT_NOT_REACHED();
3622 // This works together with setNextKeyView to splice the WebView into
3623 // the key loop similar to the way NSScrollView does this. Note that
3624 // WebFrameView has very similar code.
3625 NSWindow *window = [self window];
3626 WebFrameView *mainFrameView = [[self mainFrame] frameView];
3628 NSResponder *previousFirstResponder = [[self window] _oldFirstResponderBeforeBecoming];
3629 BOOL fromOutside = ![previousFirstResponder isKindOfClass:[NSView class]] || (![(NSView *)previousFirstResponder isDescendantOf:self] && previousFirstResponder != self);
3631 if ([window keyViewSelectionDirection] == NSSelectingPrevious) {
3632 NSView *previousValidKeyView = [self previousValidKeyView];
3633 if (previousValidKeyView != self && previousValidKeyView != mainFrameView) {
3634 _private->becomingFirstResponder = YES;
3635 _private->becomingFirstResponderFromOutside = fromOutside;
3636 [window makeFirstResponder:previousValidKeyView];
3637 _private->becomingFirstResponderFromOutside = NO;
3638 _private->becomingFirstResponder = NO;
3644 if ([mainFrameView acceptsFirstResponder]) {
3645 _private->becomingFirstResponder = YES;
3646 _private->becomingFirstResponderFromOutside = fromOutside;
3647 [window makeFirstResponder:mainFrameView];
3648 _private->becomingFirstResponderFromOutside = NO;
3649 _private->becomingFirstResponder = NO;
3656 // FIXME (Viewless): Need more code from WebHTMLView here.
3660 - (NSView *)_webcore_effectiveFirstResponder
3662 if (_private && _private->usesDocumentViews) {
3663 if (WebFrameView *frameView = [[self mainFrame] frameView])
3664 return [frameView _webcore_effectiveFirstResponder];
3666 return [super _webcore_effectiveFirstResponder];
3669 - (void)setNextKeyView:(NSView *)view
3671 if (_private && _private->usesDocumentViews) {
3672 // This works together with becomeFirstResponder to splice the WebView into
3673 // the key loop similar to the way NSScrollView does this. Note that
3674 // WebFrameView has similar code.
3675 if (WebFrameView *mainFrameView = [[self mainFrame] frameView]) {
3676 [mainFrameView setNextKeyView:view];
3681 [super setNextKeyView:view];
3684 static WebFrame *incrementFrame(WebFrame *frame, BOOL forward, BOOL wrapFlag)
3686 Frame* coreFrame = core(frame);
3688 ? coreFrame->tree()->traverseNextWithWrap(wrapFlag)
3689 : coreFrame->tree()->traversePreviousWithWrap(wrapFlag));
3692 - (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag
3694 return [self searchFor:string direction:forward caseSensitive:caseFlag wrap:wrapFlag startInSelection:NO];
3697 + (void)registerViewClass:(Class)viewClass representationClass:(Class)representationClass forMIMEType:(NSString *)MIMEType
3699 [[WebFrameView _viewTypesAllowImageTypeOmission:YES] setObject:viewClass forKey:MIMEType];
3700 [[WebDataSource _repTypesAllowImageTypeOmission:YES] setObject:representationClass forKey:MIMEType];
3702 // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
3703 // in the WebCore MIMEType registry. For now we're doing this in a safe, limited manner
3704 // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
3705 if ([viewClass class] == [WebHTMLView class])
3706 MIMETypeRegistry::getSupportedNonImageMIMETypes().add(MIMEType);
3709 - (void)setGroupName:(NSString *)groupName
3711 if (!_private->page)
3713 _private->page->setGroupName(groupName);
3716 - (NSString *)groupName
3718 if (!_private->page)
3720 return _private->page->groupName();
3723 - (double)estimatedProgress
3725 if (!_private->page)
3727 return _private->page->progress()->estimatedProgress();
3730 - (NSArray *)pasteboardTypesForSelection
3732 NSView <WebDocumentView> *documentView = [[[self _selectedOrMainFrame] frameView] documentView];
3733 if ([documentView conformsToProtocol:@protocol(WebDocumentSelection)]) {
3734 return [(NSView <WebDocumentSelection> *)documentView pasteboardTypesForSelection];
3736 return [NSArray array];
3739 - (void)writeSelectionWithPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
3741 WebFrame *frame = [self _selectedOrMainFrame];
3742 if (frame && [frame _hasSelection]) {
3743 NSView <WebDocumentView> *documentView = [[frame frameView] documentView];
3744 if ([documentView conformsToProtocol:@protocol(WebDocumentSelection)])
3745 [(NSView <WebDocumentSelection> *)documentView writeSelectionWithPasteboardTypes:types toPasteboard:pasteboard];
3749 - (NSArray *)pasteboardTypesForElement:(NSDictionary *)element
3751 if ([element objectForKey:WebElementImageURLKey] != nil) {
3752 return [NSPasteboard _web_writableTypesForImageIncludingArchive:([element objectForKey:WebElementDOMNodeKey] != nil)];
3753 } else if ([element objectForKey:WebElementLinkURLKey] != nil) {
3754 return [NSPasteboard _web_writableTypesForURL];
3755 } else if ([[element objectForKey:WebElementIsSelectedKey] boolValue]) {
3756 return [self pasteboardTypesForSelection];
3758 return [NSArray array];
3761 - (void)writeElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
3763 if ([element objectForKey:WebElementImageURLKey] != nil) {
3764 [self _writeImageForElement:element withPasteboardTypes:types toPasteboard:pasteboard];
3765 } else if ([element objectForKey:WebElementLinkURLKey] != nil) {
3766 [self _writeLinkElement:element withPasteboardTypes:types toPasteboard:pasteboard];
3767 } else if ([[element objectForKey:WebElementIsSelectedKey] boolValue]) {
3768 [self writeSelectionWithPasteboardTypes:types toPasteboard:pasteboard];
3772 - (void)moveDragCaretToPoint:(NSPoint)point
3774 if (Page* page = core(self))
3775 page->dragController()->placeDragCaret(IntPoint([self convertPoint:point toView:nil]));
3778 - (void)removeDragCaret
3780 if (Page* page = core(self))
3781 page->dragController()->dragEnded();
3784 - (void)setMainFrameURL:(NSString *)URLString
3786 [[self mainFrame] loadRequest: [NSURLRequest requestWithURL: [NSURL _web_URLWithDataAsString: URLString]]];
3789 - (NSString *)mainFrameURL
3792 ds = [[self mainFrame] provisionalDataSource];
3794 ds = [[self mainFrame] _dataSource];
3795 return [[[ds request] URL] _web_originalDataAsString];
3800 LOG (Bindings, "isLoading = %d", (int)[self _isLoading]);
3801 return [self _isLoading];
3804 - (NSString *)mainFrameTitle
3806 NSString *mainFrameTitle = [[[self mainFrame] _dataSource] pageTitle];
3807 return (mainFrameTitle != nil) ? mainFrameTitle : (NSString *)@"";
3810 - (NSImage *)mainFrameIcon
3812 return [[WebIconDatabase sharedIconDatabase] iconForURL:[[[[self mainFrame] _dataSource] _URL] _web_originalDataAsString] withSize:WebIconSmallSize];
3815 - (DOMDocument *)mainFrameDocument
3817 // only return the actual value if the state we're in gives NSTreeController
3818 // enough time to release its observers on the old model
3819 if (_private->mainFrameDocumentReady)
3820 return [[self mainFrame] DOMDocument];
3824 - (void)setDrawsBackground:(BOOL)drawsBackground
3826 if (_private->drawsBackground == drawsBackground)
3828 _private->drawsBackground = drawsBackground;
3829 [[self mainFrame] _updateBackgroundAndUpdatesWhileOffscreen];
3832 - (BOOL)drawsBackground
3834 // This method can be called beneath -[NSView dealloc] after we have cleared _private,
3835 // indirectly via -[WebFrameView viewDidMoveToWindow].
3836 return !_private || _private->drawsBackground;
3839 - (void)setShouldUpdateWhileOffscreen:(BOOL)updateWhileOffscreen
3841 if (_private->shouldUpdateWhileOffscreen == updateWhileOffscreen)
3843 _private->shouldUpdateWhileOffscreen = updateWhileOffscreen;
3844 [[self mainFrame] _updateBackgroundAndUpdatesWhileOffscreen];
3847 - (BOOL)shouldUpdateWhileOffscreen
3849 return _private->shouldUpdateWhileOffscreen;
3852 - (void)setCurrentNodeHighlight:(WebNodeHighlight *)nodeHighlight
3854 id old = _private->currentNodeHighlight;
3855 _private->currentNodeHighlight = [nodeHighlight retain];
3859 - (WebNodeHighlight *)currentNodeHighlight
3861 return _private->currentNodeHighlight;
3864 - (NSView *)previousValidKeyView
3866 NSView *result = [super previousValidKeyView];
3868 // Work around AppKit bug 6905484. If the result is a view that's inside this one, it's
3869 // possible it is the wrong answer, because the fact that it's a descendant causes the
3870 // code that implements key view redirection to fail; this means we won't redirect to
3871 // the toolbar, for example, when we hit the edge of a window. Since the bug is specific
3872 // to cases where the receiver of previousValidKeyView is an ancestor of the last valid
3873 // key view in the loop, we can sidestep it by walking along previous key views until
3874 // we find one that is not a superview, then using that to call previousValidKeyView.
3876 if (![result isDescendantOf:self])
3879 // Use a visited set so we don't loop indefinitely when walking crazy key loops.
3880 // AppKit uses such sets internally and we want our loop to be as robust as its loops.
3881 RetainPtr<CFMutableSetRef> visitedViews = CFSetCreateMutable(0, 0, 0);
3882 CFSetAddValue(visitedViews.get(), result);
3884 NSView *previousView = self;
3886 CFSetAddValue(visitedViews.get(), previousView);
3887 previousView = [previousView previousKeyView];
3888 if (!previousView || CFSetGetValue(visitedViews.get(), previousView))
3890 } while ([result isDescendantOf:previousView]);
3891 return [previousView previousValidKeyView];
3896 @implementation WebView (WebIBActions)
3898 - (IBAction)takeStringURLFrom: sender
3900 NSString *URLString = [sender stringValue];
3902 [[self mainFrame] loadRequest: [NSURLRequest requestWithURL: [NSURL _web_URLWithDataAsString: URLString]]];
3907 if (!_private->page)
3910 return !!_private->page->backForwardList()->backItem();
3913 - (BOOL)canGoForward
3915 if (!_private->page)
3918 return !!_private->page->backForwardList()->forwardItem();
3921 - (IBAction)goBack:(id)sender
3926 - (IBAction)goForward:(id)sender
3931 - (IBAction)stopLoading:(id)sender
3933 [[self mainFrame] stopLoading];
3936 - (IBAction)reload:(id)sender
3938 [[self mainFrame] reload];
3941 - (IBAction)reloadFromOrigin:(id)sender
3943 [[self mainFrame] reloadFromOrigin];
3946 // FIXME: This code should move into WebCore so that it is not duplicated in each WebKit.
3947 // (This includes canMakeTextSmaller/Larger, makeTextSmaller/Larger, and canMakeTextStandardSize/makeTextStandardSize)
3948 - (BOOL)canMakeTextSmaller
3950 return [self _canZoomOut:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3953 - (IBAction)makeTextSmaller:(id)sender
3955 return [self _zoomOut:sender isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3958 - (BOOL)canMakeTextLarger
3960 return [self _canZoomIn:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3963 - (IBAction)makeTextLarger:(id)sender
3965 return [self _zoomIn:sender isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3968 - (BOOL)canMakeTextStandardSize
3970 return [self _canResetZoom:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3973 - (IBAction)makeTextStandardSize:(id)sender
3975 return [self _resetZoom:sender isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]];
3978 - (IBAction)toggleSmartInsertDelete:(id)sender
3980 [self setSmartInsertDeleteEnabled:![self smartInsertDeleteEnabled]];
3983 - (IBAction)toggleContinuousSpellChecking:(id)sender
3985 [self setContinuousSpellCheckingEnabled:![self isContinuousSpellCheckingEnabled]];
3988 - (BOOL)_responderValidateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item
3990 id responder = [self _responderForResponderOperations];
3991 if (responder != self && [responder respondsToSelector:[item action]]) {
3992 if ([responder respondsToSelector:@selector(validateUserInterfaceItemWithoutDelegate:)])
3993 return [responder validateUserInterfaceItemWithoutDelegate:item];
3994 if ([responder respondsToSelector:@selector(validateUserInterfaceItem:)])
3995 return [responder validateUserInterfaceItem:item];
4001 #define VALIDATE(name) \
4002 else if (action == @selector(name:)) { return [self _responderValidateUserInterfaceItem:item]; }
4004 - (BOOL)validateUserInterfaceItemWithoutDelegate:(id <NSValidatedUserInterfaceItem>)item
4006 SEL action = [item action];
4008 if (action == @selector(goBack:)) {
4009 return [self canGoBack];
4010 } else if (action == @selector(goForward:)) {
4011 return [self canGoForward];
4012 } else if (action == @selector(makeTextLarger:)) {
4013 return [self canMakeTextLarger];
4014 } else if (action == @selector(makeTextSmaller:)) {
4015 return [self canMakeTextSmaller];
4016 } else if (action == @selector(makeTextStandardSize:)) {
4017 return [self canMakeTextStandardSize];
4018 } else if (action == @selector(reload:)) {
4019 return [[self mainFrame] _dataSource] != nil;
4020 } else if (action == @selector(stopLoading:)) {
4021 return [self _isLoading];
4022 } else if (action == @selector(toggleContinuousSpellChecking:)) {
4023 BOOL checkMark = NO;
4025 if ([self _continuousCheckingAllowed]) {
4026 checkMark = [self isContinuousSpellCheckingEnabled];
4029 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
4030 NSMenuItem *menuItem = (NSMenuItem *)item;
4031 [menuItem setState:checkMark ? NSOnState : NSOffState];
4034 } else if (action == @selector(toggleSmartInsertDelete:)) {
4035 BOOL checkMark = [self smartInsertDeleteEnabled];
4036 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
4037 NSMenuItem *menuItem = (NSMenuItem *)item;
4038 [menuItem setState:checkMark ? NSOnState : NSOffState];
4041 #ifndef BUILDING_ON_TIGER
4042 } else if (action == @selector(toggleGrammarChecking:)) {
4043 BOOL checkMark = [self isGrammarCheckingEnabled];
4044 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
4045 NSMenuItem *menuItem = (NSMenuItem *)item;
4046 [menuItem setState:checkMark ? NSOnState : NSOffState];
4050 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
4051 } else if (action == @selector(toggleAutomaticQuoteSubstitution:)) {
4052 BOOL checkMark = [self isAutomaticQuoteSubstitutionEnabled];
4053 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
4054 NSMenuItem *menuItem = (NSMenuItem *)item;
4055 [menuItem setState:checkMark ? NSOnState : NSOffState];
4058 } else if (action == @selector(toggleAutomaticLinkDetection:)) {
4059 BOOL checkMark = [self isAutomaticLinkDetectionEnabled];
4060 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
4061 NSMenuItem *menuItem = (NSMenuItem *)item;
4062 [menuItem setState:checkMark ? NSOnState : NSOffState];
4065 } else if (action == @selector(toggleAutomaticDashSubstitution:)) {
4066 BOOL checkMark = [self isAutomaticDashSubstitutionEnabled];
4067 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
4068 NSMenuItem *menuItem = (NSMenuItem *)item;
4069 [menuItem setState:checkMark ? NSOnState : NSOffState];
4072 } else if (action == @selector(toggleAutomaticTextReplacement:)) {
4073 BOOL checkMark = [self isAutomaticTextReplacementEnabled];
4074 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
4075 NSMenuItem *menuItem = (NSMenuItem *)item;
4076 [menuItem setState:checkMark ? NSOnState : NSOffState];
4079 } else if (action == @selector(toggleAutomaticSpellingCorrection:)) {
4080 BOOL checkMark = [self isAutomaticSpellingCorrectionEnabled];
4081 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
4082 NSMenuItem *menuItem = (NSMenuItem *)item;
4083 [menuItem setState:checkMark ? NSOnState : NSOffState];
4088 FOR_EACH_RESPONDER_SELECTOR(VALIDATE)
4093 - (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item
4095 BOOL result = [self validateUserInterfaceItemWithoutDelegate:item];
4096 return CallUIDelegateReturningBoolean(result, self, @selector(webView:validateUserInterfaceItem:defaultValidation:), item, result);
4101 @implementation WebView (WebPendingPublic)
4103 - (void)scheduleInRunLoop:(NSRunLoop *)runLoop forMode:(NSString *)mode
4105 if (runLoop && mode)
4106 core(self)->addSchedulePair(SchedulePair::create(runLoop, (CFStringRef)mode));
4109 - (void)unscheduleFromRunLoop:(NSRunLoop *)runLoop forMode:(NSString *)mode
4111 if (runLoop && mode)
4112 core(self)->removeSchedulePair(SchedulePair::create(runLoop, (CFStringRef)mode));
4115 - (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag startInSelection:(BOOL)startInSelection
4117 if (_private->closed)
4120 // Get the frame holding the selection, or start with the main frame
4121 WebFrame *startFrame = [self _selectedOrMainFrame];
4123 // Search the first frame, then all the other frames, in order
4124 NSView <WebDocumentSearching> *startSearchView = nil;
4125 WebFrame *frame = startFrame;
4127 WebFrame *nextFrame = incrementFrame(frame, forward, wrapFlag);
4129 BOOL onlyOneFrame = (frame == nextFrame);
4130 ASSERT(!onlyOneFrame || frame == startFrame);
4132 id <WebDocumentView> view = [[frame frameView] documentView];
4133 if ([view conformsToProtocol:@protocol(WebDocumentSearching)]) {
4134 NSView <WebDocumentSearching> *searchView = (NSView <WebDocumentSearching> *)view;
4136 if (frame == startFrame)
4137 startSearchView = searchView;
4140 // In some cases we have to search some content twice; see comment later in this method.
4141 // We can avoid ever doing this in the common one-frame case by passing YES for wrapFlag
4142 // here, and then bailing out before we get to the code that would search again in the
4144 BOOL wrapOnThisPass = wrapFlag && onlyOneFrame;
4145 if ([searchView conformsToProtocol:@protocol(WebDocumentIncrementalSearching)])
4146 foundString = [(NSView <WebDocumentIncrementalSearching> *)searchView searchFor:string direction:forward caseSensitive:caseFlag wrap:wrapOnThisPass startInSelection:startInSelection];
4148 foundString = [searchView searchFor:string direction:forward caseSensitive:caseFlag wrap:wrapOnThisPass];
4151 if (frame != startFrame)
4152 [startFrame _clearSelection];
4153 [[self window] makeFirstResponder:searchView];
4161 } while (frame && frame != startFrame);
4163 // 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
4164 // 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
4165 // 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
4166 // some content that we already searched on the first pass. In the worst case, we could search the entire contents of this frame twice.
4167 // To fix this, we'd need to add a mechanism to specify a range in which to search.
4168 if (wrapFlag && startSearchView) {
4170 if ([startSearchView conformsToProtocol:@protocol(WebDocumentIncrementalSearching)])
4171 foundString = [(NSView <WebDocumentIncrementalSearching> *)startSearchView searchFor:string direction:forward caseSensitive:caseFlag wrap:YES startInSelection:startInSelection];
4173 foundString = [startSearchView searchFor:string direction:forward caseSensitive:caseFlag wrap:YES];
4175 [[self window] makeFirstResponder:startSearchView];
4182 - (void)setHoverFeedbackSuspended:(BOOL)newValue
4184 if (_private->hoverFeedbackSuspended == newValue)
4187 _private->hoverFeedbackSuspended = newValue;
4189 if (_private->usesDocumentViews) {
4190 id <WebDocumentView> documentView = [[[self mainFrame] frameView] documentView];
4191 // FIXME: in a perfect world we'd do this in a general way that worked with any document view,
4192 // such as by calling a protocol method or using respondsToSelector or sending a notification.
4193 // But until there is any need for these more general solutions, we'll just hardwire it to work
4194 // with WebHTMLView.
4195 // Note that _hoverFeedbackSuspendedChanged needs to be called only on the main WebHTMLView, not
4196 // on each subframe separately.
4197 if ([documentView isKindOfClass:[WebHTMLView class]])
4198 [(WebHTMLView *)documentView _hoverFeedbackSuspendedChanged];
4202 [self _updateMouseoverWithFakeEvent];
4205 - (BOOL)isHoverFeedbackSuspended
4207 return _private->hoverFeedbackSuspended;
4210 - (void)setMainFrameDocumentReady:(BOOL)mainFrameDocumentReady
4212 // by setting this to NO, calls to mainFrameDocument are forced to return nil
4213 // setting this to YES lets it return the actual DOMDocument value
4214 // we use this to tell NSTreeController to reset its observers and clear its state
4215 if (_private->mainFrameDocumentReady == mainFrameDocumentReady)
4217 [self _willChangeValueForKey:_WebMainFrameDocumentKey];
4218 _private->mainFrameDocumentReady = mainFrameDocumentReady;
4219 [self _didChangeValueForKey:_WebMainFrameDocumentKey];
4220 // this will cause observers to call mainFrameDocument where this flag will be checked
4223 // This method name is used by Mail on Tiger (but not post-Tiger), so we shouldn't delete it
4224 // until the day comes when we're no longer supporting Mail on Tiger.
4225 - (WebFrame *)_frameForCurrentSelection
4227 return [self _selectedOrMainFrame];
4230 - (void)setTabKeyCyclesThroughElements:(BOOL)cyclesElements
4232 _private->tabKeyCyclesThroughElementsChanged = YES;
4234 _private->page->setTabKeyCyclesThroughElements(cyclesElements);
4237 - (BOOL)tabKeyCyclesThroughElements
4239 return _private->page && _private->page->tabKeyCyclesThroughElements();
4242 - (void)setScriptDebugDelegate:(id)delegate
4244 _private->scriptDebugDelegate = delegate;
4245 [self _cacheScriptDebugDelegateImplementations];
4248 [self _attachScriptDebuggerToAllFrames];
4250 [self _detachScriptDebuggerFromAllFrames];
4253 - (id)scriptDebugDelegate
4255 return _private->scriptDebugDelegate;
4258 - (void)setHistoryDelegate:(id)delegate
4260 _private->historyDelegate = delegate;
4261 [self _cacheHistoryDelegateImplementations];
4264 - (id)historyDelegate
4266 return _private->historyDelegate;
4271 Frame* coreFrame = [self _mainCoreFrame];
4274 return coreFrame->loader()->shouldClose();
4277 static NSAppleEventDescriptor* aeDescFromJSValue(ExecState* exec, JSValue jsValue)
4279 NSAppleEventDescriptor* aeDesc = 0;
4280 if (jsValue.isBoolean())
4281 return [NSAppleEventDescriptor descriptorWithBoolean:jsValue.getBoolean()];
4282 if (jsValue.isString())
4283 return [NSAppleEventDescriptor descriptorWithString:ustringToString(jsValue.getString(exec))];
4284 if (jsValue.isNumber()) {
4285 double value = jsValue.uncheckedGetNumber();
4286 int intValue = value;
4287 if (value == intValue)
4288 return [NSAppleEventDescriptor descriptorWithDescriptorType:typeSInt32 bytes:&intValue length:sizeof(intValue)];
4289 return [NSAppleEventDescriptor descriptorWithDescriptorType:typeIEEE64BitFloatingPoint bytes:&value length:sizeof(value)];
4291 if (jsValue.isObject()) {
4292 JSObject* object = jsValue.getObject();
4293 if (object->inherits(&DateInstance::info)) {
4294 DateInstance* date = static_cast<DateInstance*>(object);
4295 double ms = date->internalNumber();
4297 CFAbsoluteTime utcSeconds = ms / 1000 - kCFAbsoluteTimeIntervalSince1970;
4299 if (noErr == UCConvertCFAbsoluteTimeToLongDateTime(utcSeconds, &ldt))
4300 return [NSAppleEventDescriptor descriptorWithDescriptorType:typeLongDateTime bytes:&ldt length:sizeof(ldt)];
4303 else if (object->inherits(&JSArray::info)) {
4304 DEFINE_STATIC_LOCAL(HashSet<JSObject*>, visitedElems, ());
4305 if (!visitedElems.contains(object)) {
4306 visitedElems.add(object);
4308 JSArray* array = static_cast<JSArray*>(object);
4309 aeDesc = [NSAppleEventDescriptor listDescriptor];
4310 unsigned numItems = array->length();
4311 for (unsigned i = 0; i < numItems; ++i)
4312 [aeDesc insertDescriptor:aeDescFromJSValue(exec, array->get(exec, i)) atIndex:0];
4314 visitedElems.remove(object);
4318 JSValue primitive = object->toPrimitive(exec);
4319 if (exec->hadException()) {
4320 exec->clearException();
4321 return [NSAppleEventDescriptor nullDescriptor];
4323 return aeDescFromJSValue(exec, primitive);
4325 if (jsValue.isUndefined())
4326 return [NSAppleEventDescriptor descriptorWithTypeCode:cMissingValue];
4327 ASSERT(jsValue.isNull());
4328 return [NSAppleEventDescriptor nullDescriptor];
4331 - (NSAppleEventDescriptor *)aeDescByEvaluatingJavaScriptFromString:(NSString *)script
4333 Frame* coreFrame = [self _mainCoreFrame];
4336 if (!coreFrame->document())
4338 JSValue result = coreFrame->script()->executeScript(script, true).jsValue();
4339 if (!result) // FIXME: pass errors
4341 JSLock lock(SilenceAssertionsOnly);
4342 return aeDescFromJSValue(coreFrame->script()->globalObject(mainThreadNormalWorld())->globalExec(), result);
4345 - (BOOL)canMarkAllTextMatches
4347 WebFrame *frame = [self mainFrame];
4349 id <WebDocumentView> view = [[frame frameView] documentView];
4350 if (view && ![view conformsToProtocol:@protocol(WebMultipleTextMatches)])
4353 frame = incrementFrame(frame, YES, NO);
4359 - (NSUInteger)markAllMatchesForText:(NSString *)string caseSensitive:(BOOL)caseFlag highlight:(BOOL)highlight limit:(NSUInteger)limit
4361 WebFrame *frame = [self mainFrame];
4362 unsigned matchCount = 0;
4364 id <WebDocumentView> view = [[frame frameView] documentView];
4365 if ([view conformsToProtocol:@protocol(WebMultipleTextMatches)]) {
4366 [(NSView <WebMultipleTextMatches>*)view setMarkedTextMatchesAreHighlighted:highlight];
4368 ASSERT(limit == 0 || matchCount < limit);
4369 matchCount += [(NSView <WebMultipleTextMatches>*)view markAllMatchesForText:string caseSensitive:caseFlag limit:limit == 0 ? 0 : limit - matchCount];
4371 // Stop looking if we've reached the limit. A limit of 0 means no limit.
4372 if (limit > 0 && matchCount >= limit)
4376 frame = incrementFrame(frame, YES, NO);
4382 - (void)unmarkAllTextMatches
4384 WebFrame *frame = [self mainFrame];
4386 id <WebDocumentView> view = [[frame frameView] documentView];
4387 if ([view conformsToProtocol:@protocol(WebMultipleTextMatches)])
4388 [(NSView <WebMultipleTextMatches>*)view unmarkAllTextMatches];
4390 frame = incrementFrame(frame, YES, NO);
4394 - (NSArray *)rectsForTextMatches
4396 NSMutableArray *result = [NSMutableArray array];
4397 WebFrame *frame = [self mainFrame];
4399 id <WebDocumentView> view = [[frame frameView] documentView];
4400 if ([view conformsToProtocol:@protocol(WebMultipleTextMatches)]) {
4401 NSView <WebMultipleTextMatches> *documentView = (NSView <WebMultipleTextMatches> *)view;
4402 NSRect documentViewVisibleRect = [documentView visibleRect];
4403 NSArray *originalRects = [documentView rectsForTextMatches];
4404 unsigned rectCount = [originalRects count];
4406 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
4407 for (rectIndex = 0; rectIndex < rectCount; ++rectIndex) {
4408 NSRect r = [[originalRects objectAtIndex:rectIndex] rectValue];
4409 // Clip rect to document view's visible rect so rect is confined to subframe
4410 r = NSIntersectionRect(r, documentViewVisibleRect);
4411 if (NSIsEmptyRect(r))
4414 // Convert rect to our coordinate system
4415 r = [documentView convertRect:r toView:self];
4416 [result addObject:[NSValue valueWithRect:r]];
4417 if (rectIndex % 10 == 0) {
4419 pool = [[NSAutoreleasePool alloc] init];
4425 frame = incrementFrame(frame, YES, NO);
4431 - (void)scrollDOMRangeToVisible:(DOMRange *)range
4433 [[[[range startContainer] ownerDocument] webFrame] _scrollDOMRangeToVisible:range];
4438 return _private->allowsUndo;
4441 - (void)setAllowsUndo:(BOOL)flag
4443 _private->allowsUndo = flag;
4446 - (void)setPageSizeMultiplier:(float)m
4448 [self _setZoomMultiplier:m isTextOnly:NO];
4451 - (float)pageSizeMultiplier
4453 return ![self _realZoomMultiplierIsTextOnly] ? _private->zoomMultiplier : 1.0f;
4456 - (BOOL)canZoomPageIn
4458 return [self _canZoomIn:NO];
4461 - (IBAction)zoomPageIn:(id)sender
4463 return [self _zoomIn:sender isTextOnly:NO];
4466 - (BOOL)canZoomPageOut
4468 return [self _canZoomOut:NO];
4471 - (IBAction)zoomPageOut:(id)sender
4473 return [self _zoomOut:sender isTextOnly:NO];
4476 - (BOOL)canResetPageZoom
4478 return [self _canResetZoom:NO];
4481 - (IBAction)resetPageZoom:(id)sender
4483 return [self _resetZoom:sender isTextOnly:NO];
4486 - (void)setMediaVolume:(float)volume
4489 _private->page->setMediaVolume(volume);
4492 - (float)mediaVolume
4494 if (!_private->page)
4497 return _private->page->mediaVolume();
4500 - (void)addVisitedLinks:(NSArray *)visitedLinks
4502 PageGroup& group = core(self)->group();
4504 NSEnumerator *enumerator = [visitedLinks objectEnumerator];
4505 while (NSString *url = [enumerator nextObject]) {
4506 size_t length = [url length];
4507 const UChar* characters = CFStringGetCharactersPtr(reinterpret_cast<CFStringRef>(url));
4509 group.addVisitedLink(characters, length);
4511 Vector<UChar, 512> buffer(length);
4512 [url getCharacters:buffer.data()];
4513 group.addVisitedLink(buffer.data(), length);
4520 @implementation WebView (WebViewPrintingPrivate)
4522 - (float)_headerHeight
4524 return CallUIDelegateReturningFloat(self, @selector(webViewHeaderHeight:));
4527 - (float)_footerHeight
4529 return CallUIDelegateReturningFloat(self, @selector(webViewFooterHeight:));
4532 - (void)_drawHeaderInRect:(NSRect)rect
4534 #ifdef DEBUG_HEADER_AND_FOOTER
4535 NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
4536 [currentContext saveGraphicsState];
4537 [[NSColor yellowColor] set];
4539 [currentContext restoreGraphicsState];
4542 SEL selector = @selector(webView:drawHeaderInRect:);
4543 if (![_private->UIDelegate respondsToSelector:selector])
4546 NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
4547 [currentContext saveGraphicsState];
4550 CallUIDelegate(self, selector, rect);
4552 [currentContext restoreGraphicsState];
4555 - (void)_drawFooterInRect:(NSRect)rect
4557 #ifdef DEBUG_HEADER_AND_FOOTER
4558 NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
4559 [currentContext saveGraphicsState];
4560 [[NSColor cyanColor] set];
4562 [currentContext restoreGraphicsState];
4565 SEL selector = @selector(webView:drawFooterInRect:);
4566 if (![_private->UIDelegate respondsToSelector:selector])
4569 NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
4570 [currentContext saveGraphicsState];
4573 CallUIDelegate(self, selector, rect);
4575 [currentContext restoreGraphicsState];
4578 - (void)_adjustPrintingMarginsForHeaderAndFooter
4580 NSPrintOperation *op = [NSPrintOperation currentOperation];
4581 NSPrintInfo *info = [op printInfo];
4582 NSMutableDictionary *infoDictionary = [info dictionary];
4584 // We need to modify the top and bottom margins in the NSPrintInfo to account for the space needed by the
4585 // header and footer. Because this method can be called more than once on the same NSPrintInfo (see 5038087),
4586 // we stash away the unmodified top and bottom margins the first time this method is called, and we read from
4587 // those stashed-away values on subsequent calls.
4588 float originalTopMargin;
4589 float originalBottomMargin;
4590 NSNumber *originalTopMarginNumber = [infoDictionary objectForKey:WebKitOriginalTopPrintingMarginKey];
4591 if (!originalTopMarginNumber) {
4592 ASSERT(![infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey]);
4593 originalTopMargin = [info topMargin];
4594 originalBottomMargin = [info bottomMargin];
4595 [infoDictionary setObject:[NSNumber numberWithFloat:originalTopMargin] forKey:WebKitOriginalTopPrintingMarginKey];
4596 [infoDictionary setObject:[NSNumber numberWithFloat:originalBottomMargin] forKey:WebKitOriginalBottomPrintingMarginKey];
4598 ASSERT([originalTopMarginNumber isKindOfClass:[NSNumber class]]);
4599 ASSERT([[infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey] isKindOfClass:[NSNumber class]]);
4600 originalTopMargin = [originalTopMarginNumber floatValue];
4601 originalBottomMargin = [[infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey] floatValue];
4604 float scale = [op _web_pageSetupScaleFactor];
4605 [info setTopMargin:originalTopMargin + [self _headerHeight] * scale];
4606 [info setBottomMargin:originalBottomMargin + [self _footerHeight] * scale];
4609 - (void)_drawHeaderAndFooter
4611 // The header and footer rect height scales with the page, but the width is always
4612 // all the way across the printed page (inset by printing margins).
4613 NSPrintOperation *op = [NSPrintOperation currentOperation];
4614 float scale = [op _web_pageSetupScaleFactor];
4615 NSPrintInfo *printInfo = [op printInfo];
4616 NSSize paperSize = [printInfo paperSize];
4617 float headerFooterLeft = [printInfo leftMargin]/scale;
4618 float headerFooterWidth = (paperSize.width - ([printInfo leftMargin] + [printInfo rightMargin]))/scale;
4619 NSRect footerRect = NSMakeRect(headerFooterLeft, [printInfo bottomMargin]/scale - [self _footerHeight] ,
4620 headerFooterWidth, [self _footerHeight]);
4621 NSRect headerRect = NSMakeRect(headerFooterLeft, (paperSize.height - [printInfo topMargin])/scale,
4622 headerFooterWidth, [self _headerHeight]);
4624 [self _drawHeaderInRect:headerRect];
4625 [self _drawFooterInRect:footerRect];
4629 @implementation WebView (WebDebugBinding)
4631 - (void)addObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context
4633 LOG (Bindings, "addObserver:%p forKeyPath:%@ options:%x context:%p", anObserver, keyPath, options, context);
4634 [super addObserver:anObserver forKeyPath:keyPath options:options context:context];
4637 - (void)removeObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath
4639 LOG (Bindings, "removeObserver:%p forKeyPath:%@", anObserver, keyPath);
4640 [super removeObserver:anObserver forKeyPath:keyPath];
4645 //==========================================================================================
4648 @implementation WebView (WebViewCSS)
4650 - (DOMCSSStyleDeclaration *)computedStyleForElement:(DOMElement *)element pseudoElement:(NSString *)pseudoElement
4652 // FIXME: is this the best level for this conversion?
4653 if (pseudoElement == nil)
4654 pseudoElement = @"";
4656 return [[element ownerDocument] getComputedStyle:element pseudoElement:pseudoElement];
4661 @implementation WebView (WebViewEditing)
4663 - (DOMRange *)editableDOMRangeForPoint:(NSPoint)point
4665 Page* page = core(self);
4668 return kit(page->mainFrame()->editor()->rangeForPoint(IntPoint([self convertPoint:point toView:nil])).get());
4671 - (BOOL)_shouldChangeSelectedDOMRange:(DOMRange *)currentRange toDOMRange:(DOMRange *)proposedRange affinity:(NSSelectionAffinity)selectionAffinity stillSelecting:(BOOL)flag
4673 // 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
4674 if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_APERTURE_QUIRK) && [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.Aperture"])
4676 return [[self _editingDelegateForwarder] webView:self shouldChangeSelectedDOMRange:currentRange toDOMRange:proposedRange affinity:selectionAffinity stillSelecting:flag];
4679 - (BOOL)maintainsInactiveSelection
4684 - (void)setSelectedDOMRange:(DOMRange *)range affinity:(NSSelectionAffinity)selectionAffinity
4686 Frame* coreFrame = core([self _selectedOrMainFrame]);
4691 coreFrame->selection()->clear();
4693 // Derive the frame to use from the range passed in.
4694 // Using _selectedOrMainFrame could give us a different document than
4695 // the one the range uses.
4696 coreFrame = core([range startContainer])->document()->frame();
4700 coreFrame->selection()->setSelectedRange(core(range), core(selectionAffinity), true);
4704 - (DOMRange *)selectedDOMRange
4706 Frame* coreFrame = core([self _selectedOrMainFrame]);
4709 return kit(coreFrame->selection()->toNormalizedRange().get());
4712 - (NSSelectionAffinity)selectionAffinity
4714 Frame* coreFrame = core([self _selectedOrMainFrame]);
4716 return NSSelectionAffinityDownstream;
4717 return kit(coreFrame->selection()->affinity());
4720 - (void)setEditable:(BOOL)flag
4722 if (_private->editable != flag) {
4723 _private->editable = flag;
4724 if (!_private->tabKeyCyclesThroughElementsChanged && _private->page)
4725 _private->page->setTabKeyCyclesThroughElements(!flag);
4726 Frame* mainFrame = [self _mainCoreFrame];
4729 mainFrame->applyEditingStyleToBodyElement();
4730 // If the WebView is made editable and the selection is empty, set it to something.
4731 if (![self selectedDOMRange])
4732 mainFrame->setSelectionFromNone();
4740 return _private->editable;
4743 - (void)setTypingStyle:(DOMCSSStyleDeclaration *)style
4745 // We don't know enough at thls level to pass in a relevant WebUndoAction; we'd have to
4746 // change the API to allow this.
4747 [[self _selectedOrMainFrame] _setTypingStyle:style withUndoAction:EditActionUnspecified];
4750 - (DOMCSSStyleDeclaration *)typingStyle
4752 return [[self _selectedOrMainFrame] _typingStyle];
4755 - (void)setSmartInsertDeleteEnabled:(BOOL)flag
4757 if (_private->smartInsertDeleteEnabled != flag) {
4758 _private->smartInsertDeleteEnabled = flag;
4759 [[NSUserDefaults standardUserDefaults] setBool:_private->smartInsertDeleteEnabled forKey:WebSmartInsertDeleteEnabled];
4762 [self setSelectTrailingWhitespaceEnabled:false];
4765 - (BOOL)smartInsertDeleteEnabled
4767 return _private->smartInsertDeleteEnabled;
4770 - (void)setContinuousSpellCheckingEnabled:(BOOL)flag
4772 if (continuousSpellCheckingEnabled != flag) {
4773 continuousSpellCheckingEnabled = flag;
4774 [[NSUserDefaults standardUserDefaults] setBool:continuousSpellCheckingEnabled forKey:WebContinuousSpellCheckingEnabled];
4777 if ([self isContinuousSpellCheckingEnabled]) {
4778 [[self class] _preflightSpellChecker];
4780 [[self mainFrame] _unmarkAllMisspellings];
4784 - (BOOL)isContinuousSpellCheckingEnabled
4786 return (continuousSpellCheckingEnabled && [self _continuousCheckingAllowed]);
4789 - (NSInteger)spellCheckerDocumentTag
4791 if (!_private->hasSpellCheckerDocumentTag) {
4792 _private->spellCheckerDocumentTag = [NSSpellChecker uniqueSpellDocumentTag];
4793 _private->hasSpellCheckerDocumentTag = YES;
4795 return _private->spellCheckerDocumentTag;
4798 - (NSUndoManager *)undoManager
4800 if (!_private->allowsUndo)
4803 NSUndoManager *undoManager = [[self _editingDelegateForwarder] undoManagerForWebView:self];
4807 return [super undoManager];
4810 - (void)registerForEditingDelegateNotification:(NSString *)name selector:(SEL)selector
4812 NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
4813 if ([_private->editingDelegate respondsToSelector:selector])
4814 [defaultCenter addObserver:_private->editingDelegate selector:selector name:name object:self];
4817 - (void)setEditingDelegate:(id)delegate
4819 if (_private->editingDelegate == delegate)
4822 NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
4824 // remove notifications from current delegate
4825 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidBeginEditingNotification object:self];
4826 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidChangeNotification object:self];
4827 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidEndEditingNotification object:self];
4828 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidChangeTypingStyleNotification object:self];
4829 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidChangeSelectionNotification object:self];
4831 _private->editingDelegate = delegate;
4832 [_private->editingDelegateForwarder release];
4833 _private->editingDelegateForwarder = nil;
4835 // add notifications for new delegate
4836 [self registerForEditingDelegateNotification:WebViewDidBeginEditingNotification selector:@selector(webViewDidBeginEditing:)];
4837 [self registerForEditingDelegateNotification:WebViewDidChangeNotification selector:@selector(webViewDidChange:)];
4838 [self registerForEditingDelegateNotification:WebViewDidEndEditingNotification selector:@selector(webViewDidEndEditing:)];
4839 [self registerForEditingDelegateNotification:WebViewDidChangeTypingStyleNotification selector:@selector(webViewDidChangeTypingStyle:)];
4840 [self registerForEditingDelegateNotification:WebViewDidChangeSelectionNotification selector:@selector(webViewDidChangeSelection:)];
4843 - (id)editingDelegate
4845 return _private->editingDelegate;
4848 - (DOMCSSStyleDeclaration *)styleDeclarationWithText:(NSString *)text
4850 // FIXME: Should this really be attached to the document with the current selection?
4851 DOMCSSStyleDeclaration *decl = [[[self _selectedOrMainFrame] DOMDocument] createCSSStyleDeclaration];
4852 [decl setCssText:text];
4858 @implementation WebView (WebViewGrammarChecking)
4860 // FIXME: This method should be merged into WebViewEditing when we're not in API freeze
4861 - (BOOL)isGrammarCheckingEnabled
4863 #ifdef BUILDING_ON_TIGER
4866 return grammarCheckingEnabled;
4870 #ifndef BUILDING_ON_TIGER
4871 // FIXME: This method should be merged into WebViewEditing when we're not in API freeze
4872 - (void)setGrammarCheckingEnabled:(BOOL)flag
4874 if (grammarCheckingEnabled == flag)
4877 grammarCheckingEnabled = flag;
4878 [[NSUserDefaults standardUserDefaults] setBool:grammarCheckingEnabled forKey:WebGrammarCheckingEnabled];
4880 #ifndef BUILDING_ON_LEOPARD
4881 [[NSSpellChecker sharedSpellChecker] updatePanels];
4883 NSSpellChecker *spellChecker = [NSSpellChecker sharedSpellChecker];
4884 if ([spellChecker respondsToSelector:@selector(_updateGrammar)])
4885 [spellChecker performSelector:@selector(_updateGrammar)];
4888 // We call _preflightSpellChecker when turning continuous spell checking on, but we don't need to do that here
4889 // because grammar checking only occurs on code paths that already preflight spell checking appropriately.
4891 if (![self isGrammarCheckingEnabled])
4892 [[self mainFrame] _unmarkAllBadGrammar];
4895 // FIXME: This method should be merged into WebIBActions when we're not in API freeze
4896 - (void)toggleGrammarChecking:(id)sender
4898 [self setGrammarCheckingEnabled:![self isGrammarCheckingEnabled]];
4904 @implementation WebView (WebViewTextChecking)
4906 - (BOOL)isAutomaticQuoteSubstitutionEnabled
4908 #if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
4911 return automaticQuoteSubstitutionEnabled;
4915 - (BOOL)isAutomaticLinkDetectionEnabled
4917 #if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
4920 return automaticLinkDetectionEnabled;
4924 - (BOOL)isAutomaticDashSubstitutionEnabled
4926 #if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
4929 return automaticDashSubstitutionEnabled;
4933 - (BOOL)isAutomaticTextReplacementEnabled
4935 #if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
4938 return automaticTextReplacementEnabled;
4942 - (BOOL)isAutomaticSpellingCorrectionEnabled
4944 #if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
4947 return automaticSpellingCorrectionEnabled;
4951 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
4953 - (void)setAutomaticQuoteSubstitutionEnabled:(BOOL)flag
4955 if (automaticQuoteSubstitutionEnabled == flag)
4957 automaticQuoteSubstitutionEnabled = flag;
4958 [[NSUserDefaults standardUserDefaults] setBool:automaticQuoteSubstitutionEnabled forKey:WebAutomaticQuoteSubstitutionEnabled];
4959 [[NSSpellChecker sharedSpellChecker] updatePanels];
4962 - (void)toggleAutomaticQuoteSubstitution:(id)sender
4964 [self setAutomaticQuoteSubstitutionEnabled:![self isAutomaticQuoteSubstitutionEnabled]];
4967 - (void)setAutomaticLinkDetectionEnabled:(BOOL)flag
4969 if (automaticLinkDetectionEnabled == flag)
4971 automaticLinkDetectionEnabled = flag;
4972 [[NSUserDefaults standardUserDefaults] setBool:automaticLinkDetectionEnabled forKey:WebAutomaticLinkDetectionEnabled];
4973 [[NSSpellChecker sharedSpellChecker] updatePanels];
4976 - (void)toggleAutomaticLinkDetection:(id)sender
4978 [self setAutomaticLinkDetectionEnabled:![self isAutomaticLinkDetectionEnabled]];
4981 - (void)setAutomaticDashSubstitutionEnabled:(BOOL)flag
4983 if (automaticDashSubstitutionEnabled == flag)
4985 automaticDashSubstitutionEnabled = flag;
4986 [[NSUserDefaults standardUserDefaults] setBool:automaticDashSubstitutionEnabled forKey:WebAutomaticDashSubstitutionEnabled];
4987 [[NSSpellChecker sharedSpellChecker] updatePanels];
4990 - (void)toggleAutomaticDashSubstitution:(id)sender
4992 [self setAutomaticDashSubstitutionEnabled:![self isAutomaticDashSubstitutionEnabled]];
4995 - (void)setAutomaticTextReplacementEnabled:(BOOL)flag
4997 if (automaticTextReplacementEnabled == flag)
4999 automaticTextReplacementEnabled = flag;
5000 [[NSUserDefaults standardUserDefaults] setBool:automaticTextReplacementEnabled forKey:WebAutomaticTextReplacementEnabled];
5001 [[NSSpellChecker sharedSpellChecker] updatePanels];
5004 - (void)toggleAutomaticTextReplacement:(id)sender
5006 [self setAutomaticTextReplacementEnabled:![self isAutomaticTextReplacementEnabled]];
5009 - (void)setAutomaticSpellingCorrectionEnabled:(BOOL)flag
5011 if (automaticSpellingCorrectionEnabled == flag)
5013 automaticSpellingCorrectionEnabled = flag;
5014 [[NSUserDefaults standardUserDefaults] setBool:automaticSpellingCorrectionEnabled forKey:WebAutomaticSpellingCorrectionEnabled];
5015 [[NSSpellChecker sharedSpellChecker] updatePanels];
5018 - (void)toggleAutomaticSpellingCorrection:(id)sender
5020 [self setAutomaticSpellingCorrectionEnabled:![self isAutomaticSpellingCorrectionEnabled]];
5027 @implementation WebView (WebViewUndoableEditing)
5029 - (void)replaceSelectionWithNode:(DOMNode *)node
5031 [[self _selectedOrMainFrame] _replaceSelectionWithNode:node selectReplacement:YES smartReplace:NO matchStyle:NO];
5034 - (void)replaceSelectionWithText:(NSString *)text
5036 [[self _selectedOrMainFrame] _replaceSelectionWithText:text selectReplacement:YES smartReplace:NO];
5039 - (void)replaceSelectionWithMarkupString:(NSString *)markupString
5041 [[self _selectedOrMainFrame] _replaceSelectionWithMarkupString:markupString baseURLString:nil selectReplacement:YES smartReplace:NO];
5044 - (void)replaceSelectionWithArchive:(WebArchive *)archive
5046 [[[self _selectedOrMainFrame] _dataSource] _replaceSelectionWithArchive:archive selectReplacement:YES];
5049 - (void)deleteSelection
5051 WebFrame *webFrame = [self _selectedOrMainFrame];
5052 Frame* coreFrame = core(webFrame);
5054 coreFrame->editor()->deleteSelectionWithSmartDelete([(WebHTMLView *)[[webFrame frameView] documentView] _canSmartCopyOrDelete]);
5057 - (void)applyStyle:(DOMCSSStyleDeclaration *)style
5059 // We don't know enough at thls level to pass in a relevant WebUndoAction; we'd have to
5060 // change the API to allow this.
5061 WebFrame *webFrame = [self _selectedOrMainFrame];
5062 Frame* coreFrame = core(webFrame);
5064 coreFrame->editor()->applyStyle(core(style));
5069 @implementation WebView (WebViewEditingActions)
5071 - (void)_performResponderOperation:(SEL)selector with:(id)parameter
5073 static BOOL reentered = NO;
5075 [[self nextResponder] tryToPerform:selector with:parameter];
5079 // There are two possibilities here.
5081 // One is that WebView has been called in its role as part of the responder chain.
5082 // In that case, it's fine to call the first responder and end up calling down the
5083 // responder chain again. Later we will return here with reentered = YES and continue
5084 // past the WebView.
5086 // The other is that we are being called directly, in which case we want to pass the
5087 // selector down to the view inside us that can handle it, and continue down the
5088 // responder chain as usual.
5090 // Pass this selector down to the first responder.
5091 NSResponder *responder = [self _responderForResponderOperations];
5093 [responder tryToPerform:selector with:parameter];
5097 #define FORWARD(name) \
5098 - (void)name:(id)sender { [self _performResponderOperation:_cmd with:sender]; }
5100 FOR_EACH_RESPONDER_SELECTOR(FORWARD)
5102 - (void)insertText:(NSString *)text
5104 [self _performResponderOperation:_cmd with:text];
5109 @implementation WebView (WebViewEditingInMail)
5111 - (void)_insertNewlineInQuotedContent
5113 [[self _selectedOrMainFrame] _insertParagraphSeparatorInQuotedContent];
5116 - (void)_replaceSelectionWithNode:(DOMNode *)node matchStyle:(BOOL)matchStyle
5118 [[self _selectedOrMainFrame] _replaceSelectionWithNode:node selectReplacement:YES smartReplace:NO matchStyle:matchStyle];
5121 - (BOOL)_selectionIsCaret
5123 Frame* coreFrame = core([self _selectedOrMainFrame]);
5126 return coreFrame->selection()->isCaret();
5129 - (BOOL)_selectionIsAll
5131 Frame* coreFrame = core([self _selectedOrMainFrame]);
5134 return coreFrame->selection()->isAll(MayLeaveEditableContent);
5139 static WebFrameView *containingFrameView(NSView *view)
5141 while (view && ![view isKindOfClass:[WebFrameView class]])
5142 view = [view superview];
5143 return (WebFrameView *)view;
5146 @implementation WebView (WebFileInternal)
5148 + (void)_setCacheModel:(WebCacheModel)cacheModel
5150 if (s_didSetCacheModel && cacheModel == s_cacheModel)
5153 NSString *nsurlCacheDirectory = (NSString *)WebCFAutorelease(WKCopyFoundationCacheDirectory());
5154 if (!nsurlCacheDirectory)
5155 nsurlCacheDirectory = NSHomeDirectory();
5157 // As a fudge factor, use 1000 instead of 1024, in case the reported byte
5158 // count doesn't align exactly to a megabyte boundary.
5159 uint64_t memSize = WebMemorySize() / 1024 / 1000;
5160 unsigned long long diskFreeSize = WebVolumeFreeSize(nsurlCacheDirectory) / 1024 / 1000;
5161 NSURLCache *nsurlCache = [NSURLCache sharedURLCache];
5163 unsigned cacheTotalCapacity = 0;
5164 unsigned cacheMinDeadCapacity = 0;
5165 unsigned cacheMaxDeadCapacity = 0;
5166 double deadDecodedDataDeletionInterval = 0;
5168 unsigned pageCacheCapacity = 0;
5170 NSUInteger nsurlCacheMemoryCapacity = 0;
5171 NSUInteger nsurlCacheDiskCapacity = 0;
5173 switch (cacheModel) {
5174 case WebCacheModelDocumentViewer: {
5175 // Page cache capacity (in pages)
5176 pageCacheCapacity = 0;
5178 // Object cache capacities (in bytes)
5179 if (memSize >= 2048)
5180 cacheTotalCapacity = 96 * 1024 * 1024;
5181 else if (memSize >= 1536)
5182 cacheTotalCapacity = 64 * 1024 * 1024;
5183 else if (memSize >= 1024)
5184 cacheTotalCapacity = 32 * 1024 * 1024;
5185 else if (memSize >= 512)
5186 cacheTotalCapacity = 16 * 1024 * 1024;
5188 cacheMinDeadCapacity = 0;
5189 cacheMaxDeadCapacity = 0;
5191 // Foundation memory cache capacity (in bytes)
5192 nsurlCacheMemoryCapacity = 0;
5194 // Foundation disk cache capacity (in bytes)
5195 nsurlCacheDiskCapacity = [nsurlCache diskCapacity];
5199 case WebCacheModelDocumentBrowser: {
5200 // Page cache capacity (in pages)
5201 if (memSize >= 1024)
5202 pageCacheCapacity = 3;
5203 else if (memSize >= 512)
5204 pageCacheCapacity = 2;
5205 else if (memSize >= 256)
5206 pageCacheCapacity = 1;
5208 pageCacheCapacity = 0;
5210 // Object cache capacities (in bytes)
5211 if (memSize >= 2048)
5212 cacheTotalCapacity = 96 * 1024 * 1024;
5213 else if (memSize >= 1536)
5214 cacheTotalCapacity = 64 * 1024 * 1024;
5215 else if (memSize >= 1024)
5216 cacheTotalCapacity = 32 * 1024 * 1024;
5217 else if (memSize >= 512)
5218 cacheTotalCapacity = 16 * 1024 * 1024;
5220 cacheMinDeadCapacity = cacheTotalCapacity / 8;
5221 cacheMaxDeadCapacity = cacheTotalCapacity / 4;
5223 // Foundation memory cache capacity (in bytes)
5224 if (memSize >= 2048)
5225 nsurlCacheMemoryCapacity = 4 * 1024 * 1024;
5226 else if (memSize >= 1024)
5227 nsurlCacheMemoryCapacity = 2 * 1024 * 1024;
5228 else if (memSize >= 512)
5229 nsurlCacheMemoryCapacity = 1 * 1024 * 1024;
5231 nsurlCacheMemoryCapacity = 512 * 1024;
5233 // Foundation disk cache capacity (in bytes)
5234 if (diskFreeSize >= 16384)
5235 nsurlCacheDiskCapacity = 50 * 1024 * 1024;
5236 else if (diskFreeSize >= 8192)
5237 nsurlCacheDiskCapacity = 40 * 1024 * 1024;
5238 else if (diskFreeSize >= 4096)
5239 nsurlCacheDiskCapacity = 30 * 1024 * 1024;
5241 nsurlCacheDiskCapacity = 20 * 1024 * 1024;
5245 case WebCacheModelPrimaryWebBrowser: {
5246 // Page cache capacity (in pages)
5247 // (Research indicates that value / page drops substantially after 3 pages.)
5248 if (memSize >= 2048)
5249 pageCacheCapacity = 5;
5250 else if (memSize >= 1024)
5251 pageCacheCapacity = 4;
5252 else if (memSize >= 512)
5253 pageCacheCapacity = 3;
5254 else if (memSize >= 256)
5255 pageCacheCapacity = 2;
5257 pageCacheCapacity = 1;
5259 // Object cache capacities (in bytes)
5260 // (Testing indicates that value / MB depends heavily on content and
5261 // browsing pattern. Even growth above 128MB can have substantial
5262 // value / MB for some content / browsing patterns.)
5263 if (memSize >= 2048)
5264 cacheTotalCapacity = 128 * 1024 * 1024;
5265 else if (memSize >= 1536)
5266 cacheTotalCapacity = 96 * 1024 * 1024;
5267 else if (memSize >= 1024)
5268 cacheTotalCapacity = 64 * 1024 * 1024;
5269 else if (memSize >= 512)
5270 cacheTotalCapacity = 32 * 1024 * 1024;
5272 cacheMinDeadCapacity = cacheTotalCapacity / 4;
5273 cacheMaxDeadCapacity = cacheTotalCapacity / 2;
5275 // This code is here to avoid a PLT regression. We can remove it if we
5276 // can prove that the overall system gain would justify the regression.
5277 cacheMaxDeadCapacity = max(24u, cacheMaxDeadCapacity);
5279 deadDecodedDataDeletionInterval = 60;
5281 // Foundation memory cache capacity (in bytes)
5282 // (These values are small because WebCore does most caching itself.)
5283 if (memSize >= 1024)
5284 nsurlCacheMemoryCapacity = 4 * 1024 * 1024;
5285 else if (memSize >= 512)
5286 nsurlCacheMemoryCapacity = 2 * 1024 * 1024;
5287 else if (memSize >= 256)
5288 nsurlCacheMemoryCapacity = 1 * 1024 * 1024;
5290 nsurlCacheMemoryCapacity = 512 * 1024;
5292 // Foundation disk cache capacity (in bytes)
5293 if (diskFreeSize >= 16384)
5294 nsurlCacheDiskCapacity = 175 * 1024 * 1024;
5295 else if (diskFreeSize >= 8192)
5296 nsurlCacheDiskCapacity = 150 * 1024 * 1024;
5297 else if (diskFreeSize >= 4096)
5298 nsurlCacheDiskCapacity = 125 * 1024 * 1024;
5299 else if (diskFreeSize >= 2048)
5300 nsurlCacheDiskCapacity = 100 * 1024 * 1024;
5301 else if (diskFreeSize >= 1024)
5302 nsurlCacheDiskCapacity = 75 * 1024 * 1024;
5304 nsurlCacheDiskCapacity = 50 * 1024 * 1024;
5309 ASSERT_NOT_REACHED();
5312 #ifdef BUILDING_ON_TIGER
5313 // Don't use a big Foundation disk cache on Tiger because, according to the
5314 // PLT, the Foundation disk cache on Tiger is slower than the network.
5315 nsurlCacheDiskCapacity = [nsurlCache diskCapacity];
5318 // Don't shrink a big disk cache, since that would cause churn.
5319 nsurlCacheDiskCapacity = max(nsurlCacheDiskCapacity, [nsurlCache diskCapacity]);
5321 cache()->setCapacities(cacheMinDeadCapacity, cacheMaxDeadCapacity, cacheTotalCapacity);
5322 cache()->setDeadDecodedDataDeletionInterval(deadDecodedDataDeletionInterval);
5323 pageCache()->setCapacity(pageCacheCapacity);
5324 [nsurlCache setMemoryCapacity:nsurlCacheMemoryCapacity];
5325 [nsurlCache setDiskCapacity:nsurlCacheDiskCapacity];
5327 s_cacheModel = cacheModel;
5328 s_didSetCacheModel = YES;
5331 + (WebCacheModel)_cacheModel
5333 return s_cacheModel;
5336 + (WebCacheModel)_didSetCacheModel
5338 return s_didSetCacheModel;
5341 + (WebCacheModel)_maxCacheModelInAnyInstance
5343 WebCacheModel cacheModel = WebCacheModelDocumentViewer;
5344 NSEnumerator *enumerator = [(NSMutableSet *)allWebViewsSet objectEnumerator];
5345 while (WebPreferences *preferences = [[enumerator nextObject] preferences])
5346 cacheModel = max(cacheModel, [preferences cacheModel]);
5350 + (void)_preferencesChangedNotification:(NSNotification *)notification
5352 WebPreferences *preferences = (WebPreferences *)[notification object];
5353 ASSERT([preferences isKindOfClass:[WebPreferences class]]);
5355 WebCacheModel cacheModel = [preferences cacheModel];
5356 if (![self _didSetCacheModel] || cacheModel > [self _cacheModel])
5357 [self _setCacheModel:cacheModel];
5358 else if (cacheModel < [self _cacheModel])
5359 [self _setCacheModel:max([[WebPreferences standardPreferences] cacheModel], [self _maxCacheModelInAnyInstance])];
5362 + (void)_preferencesRemovedNotification:(NSNotification *)notification
5364 WebPreferences *preferences = (WebPreferences *)[notification object];
5365 ASSERT([preferences isKindOfClass:[WebPreferences class]]);
5367 if ([preferences cacheModel] == [self _cacheModel])
5368 [self _setCacheModel:max([[WebPreferences standardPreferences] cacheModel], [self _maxCacheModelInAnyInstance])];
5371 - (WebFrame *)_focusedFrame
5373 NSResponder *resp = [[self window] firstResponder];
5374 if (resp && [resp isKindOfClass:[NSView class]] && [(NSView *)resp isDescendantOf:[[self mainFrame] frameView]]) {
5375 WebFrameView *frameView = containingFrameView((NSView *)resp);
5376 ASSERT(frameView != nil);
5377 return [frameView webFrame];
5385 WebFrame *mainFrame = [self mainFrame];
5386 return [[mainFrame _dataSource] isLoading]
5387 || [[mainFrame provisionalDataSource] isLoading];
5390 - (WebFrameView *)_frameViewAtWindowPoint:(NSPoint)point
5392 if (_private->closed)
5394 ASSERT(_private->usesDocumentViews);
5395 NSView *view = [self hitTest:[[self superview] convertPoint:point fromView:nil]];
5396 if (![view isDescendantOf:[[self mainFrame] frameView]])
5398 WebFrameView *frameView = containingFrameView(view);
5403 + (void)_preflightSpellCheckerNow:(id)sender
5405 [[NSSpellChecker sharedSpellChecker] _preflightChosenSpellServer];
5408 + (void)_preflightSpellChecker
5410 // As AppKit does, we wish to delay tickling the shared spellchecker into existence on application launch.
5411 if ([NSSpellChecker sharedSpellCheckerExists]) {
5412 [self _preflightSpellCheckerNow:self];
5414 [self performSelector:@selector(_preflightSpellCheckerNow:) withObject:self afterDelay:2.0];
5418 - (BOOL)_continuousCheckingAllowed
5420 static BOOL allowContinuousSpellChecking = YES;
5421 static BOOL readAllowContinuousSpellCheckingDefault = NO;
5422 if (!readAllowContinuousSpellCheckingDefault) {
5423 if ([[NSUserDefaults standardUserDefaults] objectForKey:@"NSAllowContinuousSpellChecking"]) {
5424 allowContinuousSpellChecking = [[NSUserDefaults standardUserDefaults] boolForKey:@"NSAllowContinuousSpellChecking"];
5426 readAllowContinuousSpellCheckingDefault = YES;
5428 return allowContinuousSpellChecking;
5431 - (NSResponder *)_responderForResponderOperations
5433 NSResponder *responder = [[self window] firstResponder];
5434 WebFrameView *mainFrameView = [[self mainFrame] frameView];
5436 // If the current responder is outside of the webview, use our main frameView or its
5437 // document view. We also do this for subviews of self that are siblings of the main
5438 // frameView since clients might insert non-webview-related views there (see 4552713).
5439 if (responder != self && ![mainFrameView _web_firstResponderIsSelfOrDescendantView]) {
5440 responder = [mainFrameView documentView];
5442 responder = mainFrameView;
5447 - (void)_openFrameInNewWindowFromMenu:(NSMenuItem *)sender
5449 ASSERT_ARG(sender, [sender isKindOfClass:[NSMenuItem class]]);
5451 NSDictionary *element = [sender representedObject];
5452 ASSERT([element isKindOfClass:[NSDictionary class]]);
5454 WebDataSource *dataSource = [(WebFrame *)[element objectForKey:WebElementFrameKey] dataSource];
5455 NSURLRequest *request = [[dataSource request] copy];
5458 [self _openNewWindowWithRequest:request];
5462 - (void)_searchWithGoogleFromMenu:(id)sender
5464 id documentView = [[[self selectedFrame] frameView] documentView];
5465 if (![documentView conformsToProtocol:@protocol(WebDocumentText)]) {
5469 NSString *selectedString = [(id <WebDocumentText>)documentView selectedString];
5470 if ([selectedString length] == 0) {
5474 NSPasteboard *pasteboard = [NSPasteboard pasteboardWithUniqueName];
5475 [pasteboard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
5476 NSMutableString *s = [selectedString mutableCopy];
5477 const unichar nonBreakingSpaceCharacter = 0xA0;
5478 NSString *nonBreakingSpaceString = [NSString stringWithCharacters:&nonBreakingSpaceCharacter length:1];
5479 [s replaceOccurrencesOfString:nonBreakingSpaceString withString:@" " options:0 range:NSMakeRange(0, [s length])];
5480 [pasteboard setString:s forType:NSStringPboardType];
5483 // FIXME: seems fragile to use the service by name, but this is what AppKit does
5484 NSPerformService(@"Search With Google", pasteboard);
5487 - (void)_searchWithSpotlightFromMenu:(id)sender
5489 id documentView = [[[self selectedFrame] frameView] documentView];
5490 if (![documentView conformsToProtocol:@protocol(WebDocumentText)])
5493 NSString *selectedString = [(id <WebDocumentText>)documentView selectedString];
5494 if (![selectedString length])
5497 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
5498 [[NSWorkspace sharedWorkspace] showSearchResultsForQueryString:selectedString];
5500 (void)HISearchWindowShow((CFStringRef)selectedString, kNilOptions);
5504 #if USE(ACCELERATED_COMPOSITING)
5505 - (void)_clearLayerSyncLoopObserver
5507 if (!_private->layerSyncRunLoopObserver)
5510 CFRunLoopObserverInvalidate(_private->layerSyncRunLoopObserver);
5511 CFRelease(_private->layerSyncRunLoopObserver);
5512 _private->layerSyncRunLoopObserver = 0;
5516 #if ENABLE(VIDEO) && USE(GSTREAMER)
5517 - (void)_clearGlibLoopObserver
5519 if (!_private->glibRunLoopObserver)
5522 CFRunLoopObserverInvalidate(_private->glibRunLoopObserver);
5523 CFRelease(_private->glibRunLoopObserver);
5524 _private->glibRunLoopObserver = 0;
5529 @implementation WebView (WebViewInternal)
5531 + (BOOL)shouldIncludeInWebKitStatistics
5536 - (BOOL)_becomingFirstResponderFromOutside
5538 return _private->becomingFirstResponderFromOutside;
5541 #if ENABLE(ICONDATABASE)
5542 - (void)_receivedIconChangedNotification:(NSNotification *)notification
5544 // Get the URL for this notification
5545 NSDictionary *userInfo = [notification userInfo];
5546 ASSERT([userInfo isKindOfClass:[NSDictionary class]]);
5547 NSString *urlString = [userInfo objectForKey:WebIconNotificationUserInfoURLKey];
5548 ASSERT([urlString isKindOfClass:[NSString class]]);
5550 // If that URL matches the current main frame, dispatch the delegate call, which will also unregister
5551 // us for this notification
5552 if ([[self mainFrameURL] isEqualTo:urlString])
5553 [self _dispatchDidReceiveIconFromWebFrame:[self mainFrame]];
5556 - (void)_registerForIconNotification:(BOOL)listen
5559 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_receivedIconChangedNotification:) name:WebIconDatabaseDidAddIconNotification object:nil];
5561 [[NSNotificationCenter defaultCenter] removeObserver:self name:WebIconDatabaseDidAddIconNotification object:nil];
5564 - (void)_dispatchDidReceiveIconFromWebFrame:(WebFrame *)webFrame
5566 // FIXME: This willChangeValueForKey call is too late, because the icon has already changed by now.
5567 [self _willChangeValueForKey:_WebMainFrameIconKey];
5569 // 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
5570 // notification any longer
5571 [self _registerForIconNotification:NO];
5573 WebFrameLoadDelegateImplementationCache* cache = &_private->frameLoadDelegateImplementations;
5574 if (cache->didReceiveIconForFrameFunc) {
5575 Image* image = iconDatabase()->iconForPageURL(core(webFrame)->loader()->url().string(), IntSize(16, 16));
5576 if (NSImage *icon = webGetNSImage(image, NSMakeSize(16, 16)))
5577 CallFrameLoadDelegate(cache->didReceiveIconForFrameFunc, self, @selector(webView:didReceiveIcon:forFrame:), icon, webFrame);
5580 [self _didChangeValueForKey:_WebMainFrameIconKey];
5582 #endif // ENABLE(ICONDATABASE)
5584 - (void)_addObject:(id)object forIdentifier:(unsigned long)identifier
5586 ASSERT(!_private->identifierMap.contains(identifier));
5588 // If the identifier map is initially empty it means we're starting a load
5589 // of something. The semantic is that the web view should be around as long
5590 // as something is loading. Because of that we retain the web view.
5591 if (_private->identifierMap.isEmpty())
5594 _private->identifierMap.set(identifier, object);
5597 - (id)_objectForIdentifier:(unsigned long)identifier
5599 return _private->identifierMap.get(identifier).get();
5602 - (void)_removeObjectForIdentifier:(unsigned long)identifier
5604 ASSERT(_private->identifierMap.contains(identifier));
5605 _private->identifierMap.remove(identifier);
5607 // If the identifier map is now empty it means we're no longer loading anything
5608 // and we should release the web view.
5609 if (_private->identifierMap.isEmpty())
5613 - (void)_retrieveKeyboardUIModeFromPreferences:(NSNotification *)notification
5615 CFPreferencesAppSynchronize(UniversalAccessDomain);
5617 Boolean keyExistsAndHasValidFormat;
5618 int mode = CFPreferencesGetAppIntegerValue(AppleKeyboardUIMode, UniversalAccessDomain, &keyExistsAndHasValidFormat);
5620 // The keyboard access mode is reported by two bits:
5621 // Bit 0 is set if feature is on
5622 // Bit 1 is set if full keyboard access works for any control, not just text boxes and lists
5623 // We require both bits to be on.
5624 // I do not know that we would ever get one bit on and the other off since
5625 // checking the checkbox in system preferences which is marked as "Turn on full keyboard access"
5626 // turns on both bits.
5627 _private->_keyboardUIMode = (mode & 0x2) ? KeyboardAccessFull : KeyboardAccessDefault;
5629 // check for tabbing to links
5630 if ([_private->preferences tabsToLinks])
5631 _private->_keyboardUIMode = (KeyboardUIMode)(_private->_keyboardUIMode | KeyboardAccessTabsToLinks);
5634 - (KeyboardUIMode)_keyboardUIMode
5636 if (!_private->_keyboardUIModeAccessed) {
5637 _private->_keyboardUIModeAccessed = YES;
5639 [self _retrieveKeyboardUIModeFromPreferences:nil];
5641 [[NSDistributedNotificationCenter defaultCenter]
5642 addObserver:self selector:@selector(_retrieveKeyboardUIModeFromPreferences:)
5643 name:KeyboardUIModeDidChangeNotification object:nil];
5645 [[NSNotificationCenter defaultCenter]
5646 addObserver:self selector:@selector(_retrieveKeyboardUIModeFromPreferences:)
5647 name:WebPreferencesChangedNotification object:nil];
5649 return _private->_keyboardUIMode;
5652 - (void)_setInsertionPasteboard:(NSPasteboard *)pasteboard
5654 _private->insertionPasteboard = pasteboard;
5657 - (void)_selectionChanged
5659 if (_private->usesDocumentViews) {
5660 id documentView = [[[self _selectedOrMainFrame] frameView] documentView];
5661 if ([documentView isKindOfClass:[WebHTMLView class]])
5662 [documentView _selectionChanged];
5666 // FIXME (Viewless): We'll need code here.
5669 - (Frame*)_mainCoreFrame
5671 return (_private && _private->page) ? _private->page->mainFrame() : 0;
5674 - (WebFrame *)_selectedOrMainFrame
5676 WebFrame *result = [self selectedFrame];
5678 result = [self mainFrame];
5682 #if USE(ACCELERATED_COMPOSITING)
5684 - (BOOL)_needsOneShotDrawingSynchronization
5686 return _private->needsOneShotDrawingSynchronization;
5689 - (void)_setNeedsOneShotDrawingSynchronization:(BOOL)needsSynchronization
5691 _private->needsOneShotDrawingSynchronization = needsSynchronization;
5694 - (BOOL)_syncCompositingChanges
5696 Frame* frame = [self _mainCoreFrame];
5697 if (frame && frame->view())
5698 return frame->view()->syncCompositingStateRecursive();
5704 The order of events with compositing updates is this:
5706 Start of runloop End of runloop
5708 --|-------------------------------------------------------|--
5711 NSWindow update, | CA commit
5714 layerSyncRunLoopObserverCallBack
5716 To avoid flashing, we have to ensure that compositing changes (rendered via
5717 the CoreAnimation rendering display link) appear on screen at the same time
5718 as content painted into the window via the normal WebCore rendering path.
5720 CoreAnimation will commit any layer changes at the end of the runloop via
5721 its "CA commit" observer. Those changes can then appear onscreen at any time
5722 when the display link fires, which can result in unsynchronized rendering.
5724 To fix this, the GraphicsLayerCA code in WebCore does not change the CA
5725 layer tree during style changes and layout; it stores up all changes and
5726 commits them via syncCompositingState(). There are then two situations in
5727 which we can call syncCompositingState():
5729 1. When painting. FrameView::paintContents() makes a call to syncCompositingState().
5731 2. When style changes/layout have made changes to the layer tree which do not
5732 result in painting. In this case we need a run loop observer to do a
5733 syncCompositingState() at an appropriate time. The observer will keep firing
5734 until the time is right (essentially when there are no more pending layouts).
5738 static void layerSyncRunLoopObserverCallBack(CFRunLoopObserverRef, CFRunLoopActivity, void* info)
5740 WebView *webView = reinterpret_cast<WebView*>(info);
5741 NSWindow *window = [webView window];
5743 // An NSWindow may not display in the next runloop cycle after dirtying due to delayed window display logic,
5744 // in which case this observer can fire first. So if the window is due for a display, don't commit
5745 // layer changes, otherwise they'll show on screen before the view drawing.
5746 bool viewsNeedDisplay;
5748 if (window && [window _wrapsCarbonWindow])
5749 viewsNeedDisplay = HIViewGetNeedsDisplay(HIViewGetRoot(static_cast<WindowRef>([window windowRef])));
5752 viewsNeedDisplay = [window viewsNeedDisplay];
5754 if (viewsNeedDisplay)
5757 if ([webView _syncCompositingChanges]) {
5758 [webView _clearLayerSyncLoopObserver];
5759 // AppKit may have disabled screen updates, thinking an upcoming window flush will re-enable them.
5760 // In case setNeedsDisplayInRect() has prevented the window from needing to be flushed, re-enable screen
5762 if (![window isFlushWindowDisabled])
5763 [window _enableScreenUpdatesIfNeeded];
5765 // Since the WebView does not need display, -viewWillDraw will not be called. Perform pending layout now,
5766 // so that the layers draw with up-to-date layout.
5767 [webView _viewWillDrawInternal];
5771 - (void)_scheduleCompositingLayerSync
5773 if (_private->layerSyncRunLoopObserver)
5776 // Run after AppKit does its window update. If we do any painting, we'll commit
5777 // layer changes from FrameView::paintContents(), otherwise we'll commit via
5778 // _syncCompositingChanges when this observer fires.
5779 const CFIndex runLoopOrder = NSDisplayWindowRunLoopOrdering + 1;
5781 // The WebView always outlives the observer, so no need to retain/release.
5782 CFRunLoopObserverContext context = { 0, self, 0, 0, 0 };
5784 _private->layerSyncRunLoopObserver = CFRunLoopObserverCreate(NULL,
5785 kCFRunLoopBeforeWaiting | kCFRunLoopExit, true /* repeats */,
5786 runLoopOrder, layerSyncRunLoopObserverCallBack, &context);
5788 CFRunLoopAddObserver(CFRunLoopGetCurrent(), _private->layerSyncRunLoopObserver, kCFRunLoopCommonModes);
5795 - (void)_enterFullscreenForNode:(WebCore::Node*)node
5797 ASSERT(node->hasTagName(WebCore::HTMLNames::videoTag));
5798 HTMLMediaElement* videoElement = static_cast<HTMLMediaElement*>(node);
5800 if (_private->fullscreenController) {
5801 if ([_private->fullscreenController mediaElement] == videoElement) {
5802 // The backend may just warn us that the underlaying plaftormMovie()
5803 // has changed. Just force an update.
5804 [_private->fullscreenController setMediaElement:videoElement];
5805 return; // No more to do.
5808 // First exit Fullscreen for the old mediaElement.
5809 [_private->fullscreenController mediaElement]->exitFullscreen();
5810 // This previous call has to trigger _exitFullscreen,
5811 // which has to clear _private->fullscreenController.
5812 ASSERT(!_private->fullscreenController);
5814 if (!_private->fullscreenController) {
5815 _private->fullscreenController = [[WebVideoFullscreenController alloc] init];
5816 [_private->fullscreenController setMediaElement:videoElement];
5817 [_private->fullscreenController enterFullscreen:[[self window] screen]];
5820 [_private->fullscreenController setMediaElement:videoElement];
5823 - (void)_exitFullscreen
5825 if (!_private->fullscreenController)
5827 [_private->fullscreenController exitFullscreen];
5828 [_private->fullscreenController release];
5829 _private->fullscreenController = nil;
5834 #if ENABLE(VIDEO) && USE(GSTREAMER)
5836 static void glibContextIterationCallback(CFRunLoopObserverRef, CFRunLoopActivity, void*)
5838 g_main_context_iteration(0, FALSE);
5841 - (void)_scheduleGlibContextIterations
5843 if (_private->glibRunLoopObserver)
5846 NSRunLoop* myRunLoop = [NSRunLoop currentRunLoop];
5848 // Create a run loop observer and attach it to the run loop.
5849 CFRunLoopObserverContext context = {0, self, 0, 0, 0};
5850 _private->glibRunLoopObserver = CFRunLoopObserverCreate(kCFAllocatorDefault, kCFRunLoopBeforeWaiting, YES, 0, &glibContextIterationCallback, &context);
5852 if (_private->glibRunLoopObserver) {
5853 CFRunLoopRef cfLoop = [myRunLoop getCFRunLoop];
5854 CFRunLoopAddObserver(cfLoop, _private->glibRunLoopObserver, kCFRunLoopDefaultMode);
5863 @implementation WebView (WebViewGeolocation)
5865 - (void)_setGeolocationProvider:(id<WebGeolocationProvider>)geolocationProvider
5868 _private->_geolocationProvider = geolocationProvider;
5871 - (id<WebGeolocationProvider>)_geolocationProvider
5874 return _private->_geolocationProvider;
5878 - (void)_geolocationDidChangePosition:(WebGeolocationPosition *)position
5880 #if ENABLE(CLIENT_BASED_GEOLOCATION)
5881 if (_private && _private->page)
5882 _private->page->geolocationController()->positionChanged(core(position));
5886 - (void)_geolocationDidFailWithError:(NSError *)error
5888 #if ENABLE(CLIENT_BASED_GEOLOCATION)
5889 if (_private && _private->page) {
5890 RefPtr<GeolocationError> geolocatioError = GeolocationError::create(GeolocationError::PositionUnavailable, [error localizedDescription]);
5891 _private->page->geolocationController()->errorOccurred(geolocatioError.get());
5898 @implementation WebView (WebViewPrivateStyleInfo)
5900 - (JSValueRef)_computedStyleIncludingVisitedInfo:(JSContextRef)context forElement:(JSValueRef)value
5902 JSLock lock(SilenceAssertionsOnly);
5903 ExecState* exec = toJS(context);
5905 return JSValueMakeUndefined(context);
5906 JSValue jsValue = toJS(exec, value);
5907 if (!jsValue.inherits(&JSElement::s_info))
5908 return JSValueMakeUndefined(context);
5909 JSElement* jsElement = static_cast<JSElement*>(asObject(jsValue));
5910 Element* element = jsElement->impl();
5911 RefPtr<CSSComputedStyleDeclaration> style = computedStyle(element, true);
5912 return toRef(exec, toJS(exec, jsElement->globalObject(), style.get()));
5917 #ifdef BUILDING_ON_LEOPARD
5919 static IMP originalRecursivelyRemoveMailAttributesImp;
5921 static id objectElementDataAttribute(DOMHTMLObjectElement *self, SEL)
5923 return [self getAttribute:@"data"];
5926 static void recursivelyRemoveMailAttributes(DOMNode *self, SEL selector, BOOL a, BOOL b, BOOL c)
5928 // While inside this Mail function, change the behavior of -[DOMHTMLObjectElement data] back to what it used to be
5929 // before we fixed a bug in it (see http://trac.webkit.org/changeset/30044 for that change).
5931 // It's a little bit strange to patch a method defined by WebKit, but it helps keep this workaround self-contained.
5933 Method methodToPatch = class_getInstanceMethod(objc_getRequiredClass("DOMHTMLObjectElement"), @selector(data));
5934 IMP originalDataImp = method_setImplementation(methodToPatch, reinterpret_cast<IMP>(objectElementDataAttribute));
5935 originalRecursivelyRemoveMailAttributesImp(self, selector, a, b, c);
5936 method_setImplementation(methodToPatch, originalDataImp);
5941 static void patchMailRemoveAttributesMethod()
5943 #ifdef BUILDING_ON_LEOPARD
5944 if (!WKAppVersionCheckLessThan(@"com.apple.mail", -1, 4.0))
5946 Method methodToPatch = class_getInstanceMethod(objc_getRequiredClass("DOMNode"), @selector(recursivelyRemoveMailAttributes:convertObjectsToImages:convertEditableElements:));
5949 originalRecursivelyRemoveMailAttributesImp = method_setImplementation(methodToPatch, reinterpret_cast<IMP>(recursivelyRemoveMailAttributes));