Add SPI for telling WebKit to prefer pictograph glyphs over monochrome ones
[WebKit-https.git] / Source / WebKit / mac / WebView / WebView.mm
1 /*
2  * Copyright (C) 2005-2013 Apple Inc. All rights reserved.
3  * Copyright (C) 2006 David Smith (catfish.man@gmail.com)
4  * Copyright (C) 2010 Igalia S.L
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
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. 
18  *
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.
29  */
30
31 #import "WebViewInternal.h"
32 #import "WebViewData.h"
33
34 #import "DOMCSSStyleDeclarationInternal.h"
35 #import "DOMDocumentInternal.h"
36 #import "DOMNodeInternal.h"
37 #import "DOMRangeInternal.h"
38 #import "WebAlternativeTextClient.h"
39 #import "WebApplicationCache.h"
40 #import "WebBackForwardListInternal.h"
41 #import "WebBaseNetscapePluginView.h"
42 #import "WebCache.h"
43 #import "WebChromeClient.h"
44 #import "WebContextMenuClient.h"
45 #import "WebDOMOperationsPrivate.h"
46 #import "WebDataSourceInternal.h"
47 #import "WebDatabaseManagerPrivate.h"
48 #import "WebDefaultEditingDelegate.h"
49 #import "WebDefaultPolicyDelegate.h"
50 #import "WebDefaultUIDelegate.h"
51 #import "WebDelegateImplementationCaching.h"
52 #import "WebDeviceOrientationClient.h"
53 #import "WebDeviceOrientationProvider.h"
54 #import "WebDocument.h"
55 #import "WebDocumentInternal.h"
56 #import "WebDownload.h"
57 #import "WebDownloadInternal.h"
58 #import "WebDragClient.h"
59 #import "WebDynamicScrollBarsViewInternal.h"
60 #import "WebEditingDelegate.h"
61 #import "WebEditorClient.h"
62 #import "WebFormDelegatePrivate.h"
63 #import "WebFrameInternal.h"
64 #import "WebFrameLoaderClient.h"
65 #import "WebFrameNetworkingContext.h"
66 #import "WebFrameViewInternal.h"
67 #import "WebFullScreenController.h"
68 #import "WebGeolocationClient.h"
69 #import "WebGeolocationPositionInternal.h"
70 #import "WebHTMLRepresentation.h"
71 #import "WebHTMLViewInternal.h"
72 #import "WebHistoryItemInternal.h"
73 #import "WebIconDatabaseInternal.h"
74 #import "WebInspector.h"
75 #import "WebInspectorClient.h"
76 #import "WebKitErrors.h"
77 #import "WebKitFullScreenListener.h"
78 #import "WebKitLogging.h"
79 #import "WebKitNSStringExtras.h"
80 #import "WebKitStatisticsPrivate.h"
81 #import "WebKitSystemBits.h"
82 #import "WebKitVersionChecks.h"
83 #import "WebLocalizableStrings.h"
84 #import "WebNSDataExtras.h"
85 #import "WebNSDataExtrasPrivate.h"
86 #import "WebNSDictionaryExtras.h"
87 #import "WebNSEventExtras.h"
88 #import "WebNSObjectExtras.h"
89 #import "WebNSPasteboardExtras.h"
90 #import "WebNSPrintOperationExtras.h"
91 #import "WebNSURLExtras.h"
92 #import "WebNSURLRequestExtras.h"
93 #import "WebNSViewExtras.h"
94 #import "WebNodeHighlight.h"
95 #import "WebNotificationClient.h"
96 #import "WebPDFView.h"
97 #import "WebPanelAuthenticationHandler.h"
98 #import "WebPlatformStrategies.h"
99 #import "WebPluginDatabase.h"
100 #import "WebPolicyDelegate.h"
101 #import "WebPreferenceKeysPrivate.h"
102 #import "WebPreferencesPrivate.h"
103 #import "WebScriptDebugDelegate.h"
104 #import "WebScriptWorldInternal.h"
105 #import "WebStorageManagerInternal.h"
106 #import "WebSystemInterface.h"
107 #import "WebTextCompletionController.h"
108 #import "WebTextIterator.h"
109 #import "WebUIDelegate.h"
110 #import "WebUIDelegatePrivate.h"
111 #import "WebUserMediaClient.h"
112 #import <CoreFoundation/CFSet.h>
113 #import <Foundation/NSURLConnection.h>
114 #import <JavaScriptCore/APICast.h>
115 #import <JavaScriptCore/JSValueRef.h>
116 #import <WebCore/AlternativeTextUIController.h>
117 #import <WebCore/AnimationController.h>
118 #import <WebCore/ApplicationCacheStorage.h>
119 #import <WebCore/BackForwardList.h>
120 #import <WebCore/MemoryCache.h>
121 #import <WebCore/Chrome.h>
122 #import <WebCore/ColorMac.h>
123 #import <WebCore/Cursor.h>
124 #import <WebCore/DatabaseManager.h>
125 #import <WebCore/Document.h>
126 #import <WebCore/DocumentLoader.h>
127 #import <WebCore/DragController.h>
128 #import <WebCore/DragData.h>
129 #import <WebCore/DragSession.h>
130 #import <WebCore/Editor.h>
131 #import <WebCore/EventHandler.h>
132 #import <WebCore/ExceptionHandlers.h>
133 #import <WebCore/FocusController.h>
134 #import <WebCore/FrameLoader.h>
135 #import <WebCore/FrameSelection.h>
136 #import <WebCore/FrameTree.h>
137 #import <WebCore/FrameView.h>
138 #import <WebCore/GCController.h>
139 #import <WebCore/GeolocationController.h>
140 #import <WebCore/GeolocationError.h>
141 #import <WebCore/HTMLMediaElement.h>
142 #import <WebCore/HTMLNames.h>
143 #import <WebCore/HistoryController.h>
144 #import <WebCore/HistoryItem.h>
145 #import <WebCore/IconDatabase.h>
146 #import <WebCore/JSCSSStyleDeclaration.h>
147 #import <WebCore/JSDocument.h>
148 #import <WebCore/JSElement.h>
149 #import <WebCore/JSNodeList.h>
150 #import <WebCore/JSNotification.h>
151 #import <WebCore/Logging.h>
152 #import <WebCore/MIMETypeRegistry.h>
153 #import <WebCore/MainFrame.h>
154 #import <WebCore/MemoryPressureHandler.h>
155 #import <WebCore/NodeList.h>
156 #import <WebCore/Notification.h>
157 #import <WebCore/NotificationController.h>
158 #import <WebCore/Page.h>
159 #import <WebCore/PageCache.h>
160 #import <WebCore/PageGroup.h>
161 #import <WebCore/PlatformEventFactoryMac.h>
162 #import <WebCore/ProgressTracker.h>
163 #import <WebCore/RenderView.h>
164 #import <WebCore/RenderWidget.h>
165 #import <WebCore/ResourceHandle.h>
166 #import <WebCore/ResourceLoadScheduler.h>
167 #import <WebCore/ResourceRequest.h>
168 #import <WebCore/RunLoop.h>
169 #import <WebCore/RuntimeApplicationChecks.h>
170 #import <WebCore/RuntimeEnabledFeatures.h>
171 #import <WebCore/SchemeRegistry.h>
172 #import <WebCore/ScriptController.h>
173 #import <WebCore/ScriptValue.h>
174 #import <WebCore/SecurityOrigin.h>
175 #import <WebCore/SecurityPolicy.h>
176 #import <WebCore/Settings.h>
177 #import <WebCore/StylePropertySet.h>
178 #import <WebCore/SystemVersionMac.h>
179 #import <WebCore/TextResourceDecoder.h>
180 #import <WebCore/ThreadCheck.h>
181 #import <WebCore/WebCoreObjCExtras.h>
182 #import <WebCore/WebCoreView.h>
183 #import <WebCore/WebVideoFullscreenController.h>
184 #import <WebCore/Widget.h>
185 #import <WebKit/DOM.h>
186 #import <WebKit/DOMExtensions.h>
187 #import <WebKit/DOMPrivate.h>
188 #import <WebKitSystemInterface.h>
189 #import <mach-o/dyld.h>
190 #import <objc/objc-auto.h>
191 #import <objc/runtime.h>
192 #import <runtime/ArrayPrototype.h>
193 #import <runtime/DateInstance.h>
194 #import <runtime/InitializeThreading.h>
195 #import <runtime/JSLock.h>
196 #import <runtime/JSCJSValue.h>
197 #import <wtf/Assertions.h>
198 #import <wtf/HashTraits.h>
199 #import <wtf/MainThread.h>
200 #import <wtf/ObjcRuntimeExtras.h>
201 #import <wtf/RefCountedLeakCounter.h>
202 #import <wtf/RefPtr.h>
203 #import <wtf/StdLibExtras.h>
204
205 #if ENABLE(DASHBOARD_SUPPORT)
206 #import <WebKit/WebDashboardRegion.h>
207 #endif
208
209 #if ENABLE(DISK_IMAGE_CACHE) && PLATFORM(IOS)
210 #import "WebDiskImageCacheClientIOS.h"
211 #import <WebCore/DiskImageCacheIOS.h>
212 #endif
213
214 #if USE(GLIB)
215 #import <glib.h>
216 #endif
217
218 @interface NSSpellChecker (WebNSSpellCheckerDetails)
219 - (void)_preflightChosenSpellServer;
220 @end
221
222 @interface NSView (WebNSViewDetails)
223 - (NSView *)_hitTest:(NSPoint *)aPoint dragTypes:(NSSet *)types;
224 - (void)_autoscrollForDraggingInfo:(id)dragInfo timeDelta:(NSTimeInterval)repeatDelta;
225 - (BOOL)_shouldAutoscrollForDraggingInfo:(id)dragInfo;
226 @end
227
228 @interface NSWindow (WebNSWindowDetails)
229 - (id)_oldFirstResponderBeforeBecoming;
230 - (void)_enableScreenUpdatesIfNeeded;
231 - (BOOL)_wrapsCarbonWindow;
232 - (BOOL)_hasKeyAppearance;
233 @end
234
235 using namespace WebCore;
236 using namespace JSC;
237
238 #if defined(__ppc__) || defined(__ppc64__)
239 #define PROCESSOR "PPC"
240 #elif defined(__i386__) || defined(__x86_64__)
241 #define PROCESSOR "Intel"
242 #else
243 #error Unknown architecture
244 #endif
245
246 #define FOR_EACH_RESPONDER_SELECTOR(macro) \
247 macro(alignCenter) \
248 macro(alignJustified) \
249 macro(alignLeft) \
250 macro(alignRight) \
251 macro(capitalizeWord) \
252 macro(centerSelectionInVisibleArea) \
253 macro(changeAttributes) \
254 macro(changeBaseWritingDirection) \
255 macro(changeBaseWritingDirectionToLTR) \
256 macro(changeBaseWritingDirectionToRTL) \
257 macro(changeColor) \
258 macro(changeDocumentBackgroundColor) \
259 macro(changeFont) \
260 macro(changeSpelling) \
261 macro(checkSpelling) \
262 macro(complete) \
263 macro(copy) \
264 macro(copyFont) \
265 macro(cut) \
266 macro(delete) \
267 macro(deleteBackward) \
268 macro(deleteBackwardByDecomposingPreviousCharacter) \
269 macro(deleteForward) \
270 macro(deleteToBeginningOfLine) \
271 macro(deleteToBeginningOfParagraph) \
272 macro(deleteToEndOfLine) \
273 macro(deleteToEndOfParagraph) \
274 macro(deleteToMark) \
275 macro(deleteWordBackward) \
276 macro(deleteWordForward) \
277 macro(ignoreSpelling) \
278 macro(indent) \
279 macro(insertBacktab) \
280 macro(insertLineBreak) \
281 macro(insertNewline) \
282 macro(insertNewlineIgnoringFieldEditor) \
283 macro(insertParagraphSeparator) \
284 macro(insertTab) \
285 macro(insertTabIgnoringFieldEditor) \
286 macro(lowercaseWord) \
287 macro(makeBaseWritingDirectionLeftToRight) \
288 macro(makeBaseWritingDirectionRightToLeft) \
289 macro(makeTextWritingDirectionLeftToRight) \
290 macro(makeTextWritingDirectionNatural) \
291 macro(makeTextWritingDirectionRightToLeft) \
292 macro(moveBackward) \
293 macro(moveBackwardAndModifySelection) \
294 macro(moveDown) \
295 macro(moveDownAndModifySelection) \
296 macro(moveForward) \
297 macro(moveForwardAndModifySelection) \
298 macro(moveLeft) \
299 macro(moveLeftAndModifySelection) \
300 macro(moveParagraphBackwardAndModifySelection) \
301 macro(moveParagraphForwardAndModifySelection) \
302 macro(moveRight) \
303 macro(moveRightAndModifySelection) \
304 macro(moveToBeginningOfDocument) \
305 macro(moveToBeginningOfDocumentAndModifySelection) \
306 macro(moveToBeginningOfLine) \
307 macro(moveToBeginningOfLineAndModifySelection) \
308 macro(moveToBeginningOfParagraph) \
309 macro(moveToBeginningOfParagraphAndModifySelection) \
310 macro(moveToBeginningOfSentence) \
311 macro(moveToBeginningOfSentenceAndModifySelection) \
312 macro(moveToEndOfDocument) \
313 macro(moveToEndOfDocumentAndModifySelection) \
314 macro(moveToEndOfLine) \
315 macro(moveToEndOfLineAndModifySelection) \
316 macro(moveToEndOfParagraph) \
317 macro(moveToEndOfParagraphAndModifySelection) \
318 macro(moveToEndOfSentence) \
319 macro(moveToEndOfSentenceAndModifySelection) \
320 macro(moveToLeftEndOfLine) \
321 macro(moveToLeftEndOfLineAndModifySelection) \
322 macro(moveToRightEndOfLine) \
323 macro(moveToRightEndOfLineAndModifySelection) \
324 macro(moveUp) \
325 macro(moveUpAndModifySelection) \
326 macro(moveWordBackward) \
327 macro(moveWordBackwardAndModifySelection) \
328 macro(moveWordForward) \
329 macro(moveWordForwardAndModifySelection) \
330 macro(moveWordLeft) \
331 macro(moveWordLeftAndModifySelection) \
332 macro(moveWordRight) \
333 macro(moveWordRightAndModifySelection) \
334 macro(orderFrontSubstitutionsPanel) \
335 macro(outdent) \
336 macro(overWrite) \
337 macro(pageDown) \
338 macro(pageDownAndModifySelection) \
339 macro(pageUp) \
340 macro(pageUpAndModifySelection) \
341 macro(paste) \
342 macro(pasteAsPlainText) \
343 macro(pasteAsRichText) \
344 macro(pasteFont) \
345 macro(performFindPanelAction) \
346 macro(scrollLineDown) \
347 macro(scrollLineUp) \
348 macro(scrollPageDown) \
349 macro(scrollPageUp) \
350 macro(scrollToBeginningOfDocument) \
351 macro(scrollToEndOfDocument) \
352 macro(selectAll) \
353 macro(selectLine) \
354 macro(selectParagraph) \
355 macro(selectSentence) \
356 macro(selectToMark) \
357 macro(selectWord) \
358 macro(setMark) \
359 macro(showGuessPanel) \
360 macro(startSpeaking) \
361 macro(stopSpeaking) \
362 macro(subscript) \
363 macro(superscript) \
364 macro(swapWithMark) \
365 macro(takeFindStringFromSelection) \
366 macro(toggleBaseWritingDirection) \
367 macro(transpose) \
368 macro(underline) \
369 macro(unscript) \
370 macro(uppercaseWord) \
371 macro(yank) \
372 macro(yankAndSelect) \
373
374 #define WebKitOriginalTopPrintingMarginKey @"WebKitOriginalTopMargin"
375 #define WebKitOriginalBottomPrintingMarginKey @"WebKitOriginalBottomMargin"
376
377 #define KeyboardUIModeDidChangeNotification @"com.apple.KeyboardUIModeDidChange"
378 #define AppleKeyboardUIMode CFSTR("AppleKeyboardUIMode")
379 #define UniversalAccessDomain CFSTR("com.apple.universalaccess")
380
381 static BOOL s_didSetCacheModel;
382 static WebCacheModel s_cacheModel = WebCacheModelDocumentViewer;
383
384 #ifndef NDEBUG
385 static const char webViewIsOpen[] = "At least one WebView is still open.";
386 #endif
387
388 @interface NSObject (WebValidateWithoutDelegate)
389 - (BOOL)validateUserInterfaceItemWithoutDelegate:(id <NSValidatedUserInterfaceItem>)item;
390 @end
391
392 @interface _WebSafeForwarder : NSObject
393 {
394     id target; // Non-retained. Don't retain delegates.
395     id defaultTarget;
396 }
397 - (id)initWithTarget:(id)target defaultTarget:(id)defaultTarget;
398 @end
399
400 FindOptions coreOptions(WebFindOptions options)
401 {
402     return (options & WebFindOptionsCaseInsensitive ? CaseInsensitive : 0)
403         | (options & WebFindOptionsAtWordStarts ? AtWordStarts : 0)
404         | (options & WebFindOptionsTreatMedialCapitalAsWordStart ? TreatMedialCapitalAsWordStart : 0)
405         | (options & WebFindOptionsBackwards ? Backwards : 0)
406         | (options & WebFindOptionsWrapAround ? WrapAround : 0)
407         | (options & WebFindOptionsStartInSelection ? StartInSelection : 0);
408 }
409
410 LayoutMilestones coreLayoutMilestones(WebLayoutMilestones milestones)
411 {
412     return (milestones & WebDidFirstLayout ? DidFirstLayout : 0)
413         | (milestones & WebDidFirstVisuallyNonEmptyLayout ? DidFirstVisuallyNonEmptyLayout : 0)
414         | (milestones & WebDidHitRelevantRepaintedObjectsAreaThreshold ? DidHitRelevantRepaintedObjectsAreaThreshold : 0);
415 }
416
417 WebLayoutMilestones kitLayoutMilestones(LayoutMilestones milestones)
418 {
419     return (milestones & DidFirstLayout ? WebDidFirstLayout : 0)
420         | (milestones & DidFirstVisuallyNonEmptyLayout ? WebDidFirstVisuallyNonEmptyLayout : 0)
421         | (milestones & DidHitRelevantRepaintedObjectsAreaThreshold ? WebDidHitRelevantRepaintedObjectsAreaThreshold : 0);
422 }
423
424 static PageVisibilityState core(WebPageVisibilityState visibilityState)
425 {
426     switch (visibilityState) {
427     case WebPageVisibilityStateVisible:
428         return PageVisibilityStateVisible;
429     case WebPageVisibilityStateHidden:
430         return PageVisibilityStateHidden;
431     case WebPageVisibilityStatePrerender:
432         return PageVisibilityStatePrerender;
433     case WebPageVisibilityStateUnloaded:
434         return PageVisibilityStateUnloaded;
435     }
436
437     ASSERT_NOT_REACHED();
438     return PageVisibilityStateVisible;
439 }
440
441 static WebPageVisibilityState kit(PageVisibilityState visibilityState)
442 {
443     switch (visibilityState) {
444     case PageVisibilityStateVisible:
445         return WebPageVisibilityStateVisible;
446     case PageVisibilityStateHidden:
447         return WebPageVisibilityStateHidden;
448     case PageVisibilityStatePrerender:
449         return WebPageVisibilityStatePrerender;
450     case PageVisibilityStateUnloaded:
451         return WebPageVisibilityStateUnloaded;
452     }
453
454     ASSERT_NOT_REACHED();
455     return WebPageVisibilityStateVisible;
456 }
457
458 @interface WebView (WebFileInternal)
459 - (float)_deviceScaleFactor;
460 - (BOOL)_isLoading;
461 - (WebFrameView *)_frameViewAtWindowPoint:(NSPoint)point;
462 - (WebFrame *)_focusedFrame;
463 + (void)_preflightSpellChecker;
464 - (BOOL)_continuousCheckingAllowed;
465 - (NSResponder *)_responderForResponderOperations;
466 #if USE(GLIB)
467 - (void)_clearGlibLoopObserver;
468 #endif
469 @end
470
471 NSString *WebElementDOMNodeKey =            @"WebElementDOMNode";
472 NSString *WebElementFrameKey =              @"WebElementFrame";
473 NSString *WebElementImageKey =              @"WebElementImage";
474 NSString *WebElementImageAltStringKey =     @"WebElementImageAltString";
475 NSString *WebElementImageRectKey =          @"WebElementImageRect";
476 NSString *WebElementImageURLKey =           @"WebElementImageURL";
477 NSString *WebElementIsSelectedKey =         @"WebElementIsSelected";
478 NSString *WebElementLinkLabelKey =          @"WebElementLinkLabel";
479 NSString *WebElementLinkTargetFrameKey =    @"WebElementTargetFrame";
480 NSString *WebElementLinkTitleKey =          @"WebElementLinkTitle";
481 NSString *WebElementLinkURLKey =            @"WebElementLinkURL";
482 NSString *WebElementMediaURLKey =           @"WebElementMediaURL";
483 NSString *WebElementSpellingToolTipKey =    @"WebElementSpellingToolTip";
484 NSString *WebElementTitleKey =              @"WebElementTitle";
485 NSString *WebElementLinkIsLiveKey =         @"WebElementLinkIsLive";
486 NSString *WebElementIsInScrollBarKey =      @"WebElementIsInScrollBar";
487 NSString *WebElementIsContentEditableKey =  @"WebElementIsContentEditableKey";
488
489 NSString *WebViewProgressStartedNotification =          @"WebProgressStartedNotification";
490 NSString *WebViewProgressEstimateChangedNotification =  @"WebProgressEstimateChangedNotification";
491 NSString *WebViewProgressFinishedNotification =         @"WebProgressFinishedNotification";
492
493 NSString * const WebViewDidBeginEditingNotification =         @"WebViewDidBeginEditingNotification";
494 NSString * const WebViewDidChangeNotification =               @"WebViewDidChangeNotification";
495 NSString * const WebViewDidEndEditingNotification =           @"WebViewDidEndEditingNotification";
496 NSString * const WebViewDidChangeTypingStyleNotification =    @"WebViewDidChangeTypingStyleNotification";
497 NSString * const WebViewDidChangeSelectionNotification =      @"WebViewDidChangeSelectionNotification";
498
499 enum { WebViewVersion = 4 };
500
501 #define timedLayoutSize 4096
502
503 static NSMutableSet *schemesWithRepresentationsSet;
504
505 NSString *_WebCanGoBackKey =            @"canGoBack";
506 NSString *_WebCanGoForwardKey =         @"canGoForward";
507 NSString *_WebEstimatedProgressKey =    @"estimatedProgress";
508 NSString *_WebIsLoadingKey =            @"isLoading";
509 NSString *_WebMainFrameIconKey =        @"mainFrameIcon";
510 NSString *_WebMainFrameTitleKey =       @"mainFrameTitle";
511 NSString *_WebMainFrameURLKey =         @"mainFrameURL";
512 NSString *_WebMainFrameDocumentKey =    @"mainFrameDocument";
513
514 NSString *_WebViewDidStartAcceleratedCompositingNotification = @"_WebViewDidStartAcceleratedCompositing";
515 NSString * const WebViewWillCloseNotification = @"WebViewWillCloseNotification";
516
517 NSString *WebKitKerningAndLigaturesEnabledByDefaultDefaultsKey = @"WebKitKerningAndLigaturesEnabledByDefault";
518
519 @interface WebProgressItem : NSObject
520 {
521 @public
522     long long bytesReceived;
523     long long estimatedLength;
524 }
525 @end
526
527 @implementation WebProgressItem
528 @end
529
530 static BOOL continuousSpellCheckingEnabled;
531 static BOOL grammarCheckingEnabled;
532 static BOOL automaticQuoteSubstitutionEnabled;
533 static BOOL automaticLinkDetectionEnabled;
534 static BOOL automaticDashSubstitutionEnabled;
535 static BOOL automaticTextReplacementEnabled;
536 static BOOL automaticSpellingCorrectionEnabled;
537
538 @implementation WebView (AllWebViews)
539
540 static CFSetCallBacks NonRetainingSetCallbacks = {
541     0,
542     NULL,
543     NULL,
544     CFCopyDescription,
545     CFEqual,
546     CFHash
547 };
548
549 static CFMutableSetRef allWebViewsSet;
550
551 + (void)_makeAllWebViewsPerformSelector:(SEL)selector
552 {
553     if (!allWebViewsSet)
554         return;
555
556     [(NSMutableSet *)allWebViewsSet makeObjectsPerformSelector:selector];
557 }
558
559 - (void)_removeFromAllWebViewsSet
560 {
561     if (allWebViewsSet)
562         CFSetRemoveValue(allWebViewsSet, self);
563 }
564
565 - (void)_addToAllWebViewsSet
566 {
567     if (!allWebViewsSet)
568         allWebViewsSet = CFSetCreateMutable(NULL, 0, &NonRetainingSetCallbacks);
569
570     CFSetSetValue(allWebViewsSet, self);
571 }
572
573 @end
574
575 @implementation WebView (WebPrivate)
576
577 static NSString *systemMarketingVersionForUserAgentString()
578 {
579     // Use underscores instead of dots because when we first added the Mac OS X version to the user agent string
580     // we were concerned about old DHTML libraries interpreting "4." as Netscape 4. That's no longer a concern for us
581     // but we're sticking with the underscores for compatibility with the format used by older versions of Safari.
582     return [systemMarketingVersion() stringByReplacingOccurrencesOfString:@"." withString:@"_"];
583 }
584
585 static NSString *createUserVisibleWebKitVersionString()
586 {
587     // If the version is 4 digits long or longer, then the first digit represents
588     // the version of the OS. Our user agent string should not include this first digit,
589     // so strip it off and report the rest as the version. <rdar://problem/4997547>
590     NSString *fullVersion = [[NSBundle bundleForClass:[WebView class]] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey];
591     NSRange nonDigitRange = [fullVersion rangeOfCharacterFromSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]];
592     if (nonDigitRange.location == NSNotFound && [fullVersion length] >= 4)
593         return [[fullVersion substringFromIndex:1] copy];
594     if (nonDigitRange.location != NSNotFound && nonDigitRange.location >= 4)
595         return [[fullVersion substringFromIndex:1] copy];
596     return [fullVersion copy];
597 }
598
599 + (NSString *)_standardUserAgentWithApplicationName:(NSString *)applicationName
600 {
601     // Note: Do *not* move the initialization of osVersion nor webKitVersion into the declaration.
602     // Garbage collection won't correctly mark the global variable in that case <rdar://problem/5733674>.
603     static NSString *osVersion;
604     static NSString *webKitVersion;
605     if (!osVersion)
606         osVersion = [systemMarketingVersionForUserAgentString() retain];
607     if (!webKitVersion)
608         webKitVersion = createUserVisibleWebKitVersionString();
609     if ([applicationName length])
610         return [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; " PROCESSOR " Mac OS X %@) AppleWebKit/%@ (KHTML, like Gecko) %@", osVersion, webKitVersion, applicationName];
611     return [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; " PROCESSOR " Mac OS X %@) AppleWebKit/%@ (KHTML, like Gecko)", osVersion, webKitVersion];
612 }
613
614 + (void)_reportException:(JSValueRef)exception inContext:(JSContextRef)context
615 {
616     if (!exception || !context)
617         return;
618
619     JSC::ExecState* execState = toJS(context);
620     JSLockHolder lock(execState);
621
622     // Make sure the context has a DOMWindow global object, otherwise this context didn't originate from a WebView.
623     if (!toJSDOMWindow(execState->lexicalGlobalObject()))
624         return;
625
626     reportException(execState, toJS(execState, exception));
627 }
628
629 static void WebKitInitializeApplicationCachePathIfNecessary()
630 {
631     static BOOL initialized = NO;
632     if (initialized)
633         return;
634
635     NSString *appName = [[NSBundle mainBundle] bundleIdentifier];
636     if (!appName)
637         appName = [[NSProcessInfo processInfo] processName];
638
639     ASSERT(appName);
640
641     NSString* cacheDir = [NSString _webkit_localCacheDirectoryWithBundleIdentifier:appName];
642
643     cacheStorage().setCacheDirectory(cacheDir);
644     initialized = YES;
645 }
646
647 static bool shouldEnableLoadDeferring()
648 {
649     return !applicationIsAdobeInstaller();
650 }
651
652 static bool shouldRestrictWindowFocus()
653 {
654     return !applicationIsHRBlock();
655 }
656
657 - (void)_dispatchPendingLoadRequests
658 {
659     resourceLoadScheduler()->servePendingRequests();
660 }
661
662 - (void)_registerDraggedTypes
663 {
664     NSArray *editableTypes = [WebHTMLView _insertablePasteboardTypes];
665     NSArray *URLTypes = [NSPasteboard _web_dragTypesForURL];
666     NSMutableSet *types = [[NSMutableSet alloc] initWithArray:editableTypes];
667     [types addObjectsFromArray:URLTypes];
668     [self registerForDraggedTypes:[types allObjects]];
669     [types release];
670 }
671
672 static bool needsOutlookQuirksScript()
673 {
674     static bool isOutlookNeedingQuirksScript = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_HTML5_PARSER)
675         && applicationIsMicrosoftOutlook();
676     return isOutlookNeedingQuirksScript;
677 }
678
679 static NSString *leakOutlookQuirksUserScriptContents()
680 {
681     NSString *scriptPath = [[NSBundle bundleForClass:[WebView class]] pathForResource:@"OutlookQuirksUserScript" ofType:@"js"];
682     NSStringEncoding encoding;
683     return [[NSString alloc] initWithContentsOfFile:scriptPath usedEncoding:&encoding error:0];
684 }
685
686 -(void)_injectOutlookQuirksScript
687 {
688     static NSString *outlookQuirksScriptContents = leakOutlookQuirksUserScriptContents();
689     core(self)->group().addUserScriptToWorld(*core([WebScriptWorld world]),
690         outlookQuirksScriptContents, URL(), Vector<String>(), Vector<String>(), InjectAtDocumentEnd, InjectInAllFrames);
691 }
692
693 static bool shouldRespectPriorityInCSSAttributeSetters()
694 {
695     static bool isIAdProducerNeedingAttributeSetterQuirk = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_CSS_ATTRIBUTE_SETTERS_IGNORING_PRIORITY)
696         && [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.iAdProducer"];
697     return isIAdProducerNeedingAttributeSetterQuirk;
698 }
699
700 static bool shouldUseLegacyBackgroundSizeShorthandBehavior()
701 {
702     static bool shouldUseLegacyBackgroundSizeShorthandBehavior = applicationIsVersions()
703         && !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_LEGACY_BACKGROUNDSIZE_SHORTHAND_BEHAVIOR);
704     return shouldUseLegacyBackgroundSizeShorthandBehavior;
705 }
706
707 - (void)_commonInitializationWithFrameName:(NSString *)frameName groupName:(NSString *)groupName
708 {
709     WebCoreThreadViolationCheckRoundTwo();
710
711 #ifndef NDEBUG
712     WTF::RefCountedLeakCounter::suppressMessages(webViewIsOpen);
713 #endif
714     
715     WebPreferences *standardPreferences = [WebPreferences standardPreferences];
716     [standardPreferences willAddToWebView];
717
718     _private->preferences = [standardPreferences retain];
719     _private->mainFrameDocumentReady = NO;
720     _private->drawsBackground = YES;
721     _private->backgroundColor = [[NSColor colorWithDeviceWhite:1 alpha:1] retain];
722     _private->includesFlattenedCompositingLayersWhenDrawingToBitmap = YES;
723
724     NSRect f = [self frame];
725     WebFrameView *frameView = [[WebFrameView alloc] initWithFrame: NSMakeRect(0,0,f.size.width,f.size.height)];
726     [frameView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
727     [self addSubview:frameView];
728     [frameView release];
729
730     static bool didOneTimeInitialization = false;
731     if (!didOneTimeInitialization) {
732 #if !LOG_DISABLED
733         WebKitInitializeLoggingChannelsIfNecessary();
734         WebCore::initializeLoggingChannelsIfNecessary();
735 #endif // !LOG_DISABLED
736
737         // Initialize our platform strategies first before invoking the rest
738         // of the initialization code which may depend on the strategies.
739         WebPlatformStrategies::initializeIfNecessary();
740
741 #if ENABLE(SQL_DATABASE)
742         [WebDatabaseManager sharedWebDatabaseManager];
743 #endif
744
745         WebKitInitializeStorageIfNecessary();
746         WebKitInitializeApplicationCachePathIfNecessary();
747 #if ENABLE(DISK_IMAGE_CACHE) && PLATFORM(IOS)
748         WebKitInitializeWebDiskImageCache();
749 #endif
750         
751         Settings::setDefaultMinDOMTimerInterval(0.004);
752         
753         Settings::setShouldRespectPriorityInCSSAttributeSetters(shouldRespectPriorityInCSSAttributeSetters());
754
755         didOneTimeInitialization = true;
756     }
757
758     Page::PageClients pageClients;
759     pageClients.chromeClient = new WebChromeClient(self);
760     pageClients.contextMenuClient = new WebContextMenuClient(self);
761     pageClients.editorClient = new WebEditorClient(self);
762 #if ENABLE(DRAG_SUPPORT)
763     pageClients.dragClient = new WebDragClient(self);
764 #endif
765     pageClients.inspectorClient = new WebInspectorClient(self);
766     pageClients.alternativeTextClient = new WebAlternativeTextClient(self);
767     pageClients.loaderClientForMainFrame = new WebFrameLoaderClient;
768     _private->page = new Page(pageClients);
769 #if ENABLE(GEOLOCATION)
770     WebCore::provideGeolocationTo(_private->page, new WebGeolocationClient(self));
771 #endif
772 #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
773     WebCore::provideNotification(_private->page, new WebNotificationClient(self));
774 #endif
775 #if ENABLE(DEVICE_ORIENTATION)
776     WebCore::provideDeviceOrientationTo(_private->page, new WebDeviceOrientationClient(self));
777 #endif
778 #if ENABLE(MEDIA_STREAM)
779     WebCore::provideUserMediaTo(_private->page, new WebUserMediaClient(self));
780 #endif
781
782     _private->page->setCanStartMedia([self window]);
783     _private->page->settings().setLocalStorageDatabasePath([[self preferences] _localStorageDatabasePath]);
784     _private->page->settings().setUseLegacyBackgroundSizeShorthandBehavior(shouldUseLegacyBackgroundSizeShorthandBehavior());
785
786     if (needsOutlookQuirksScript()) {
787         _private->page->settings().setShouldInjectUserScriptsInInitialEmptyDocument(true);
788         [self _injectOutlookQuirksScript];
789     }
790
791     if ([[NSUserDefaults standardUserDefaults] objectForKey:WebSmartInsertDeleteEnabled])
792         [self setSmartInsertDeleteEnabled:[[NSUserDefaults standardUserDefaults] boolForKey:WebSmartInsertDeleteEnabled]];
793
794     [WebFrame _createMainFrameWithPage:_private->page frameName:frameName frameView:frameView];
795
796     NSRunLoop *runLoop = [NSRunLoop mainRunLoop];
797
798     if (WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_LOADING_DURING_COMMON_RUNLOOP_MODES))
799         [self scheduleInRunLoop:runLoop forMode:(NSString *)kCFRunLoopCommonModes];
800     else
801         [self scheduleInRunLoop:runLoop forMode:NSDefaultRunLoopMode];
802
803     [self _addToAllWebViewsSet];
804     [self setGroupName:groupName];
805     
806     // If there's already a next key view (e.g., from a nib), wire it up to our
807     // contained frame view. In any case, wire our next key view up to the our
808     // contained frame view. This works together with our becomeFirstResponder 
809     // and setNextKeyView overrides.
810     NSView *nextKeyView = [self nextKeyView];
811     if (nextKeyView && nextKeyView != frameView)
812         [frameView setNextKeyView:nextKeyView];
813     [super setNextKeyView:frameView];
814
815     if ([[self class] shouldIncludeInWebKitStatistics])
816         ++WebViewCount;
817
818     [self _registerDraggedTypes];
819
820     [self _setVisibilityState:([self _isViewVisible] ? WebPageVisibilityStateVisible : WebPageVisibilityStateHidden) isInitialState:YES];
821
822     WebPreferences *prefs = [self preferences];
823     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:)
824                                                  name:WebPreferencesChangedInternalNotification object:prefs];
825
826     [self _preferencesChanged:[self preferences]];
827     [[self preferences] _postPreferencesChangedAPINotification];
828
829     memoryPressureHandler().install();
830
831     if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_LOCAL_RESOURCE_SECURITY_RESTRICTION)) {
832         // Originally, we allowed all local loads.
833         SecurityPolicy::setLocalLoadPolicy(SecurityPolicy::AllowLocalLoadsForAll);
834     } else if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_MORE_STRICT_LOCAL_RESOURCE_SECURITY_RESTRICTION)) {
835         // Later, we allowed local loads for local URLs and documents loaded
836         // with substitute data.
837         SecurityPolicy::setLocalLoadPolicy(SecurityPolicy::AllowLocalLoadsForLocalAndSubstituteData);
838     }
839
840     if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_CONTENT_SNIFFING_FOR_FILE_URLS))
841         ResourceHandle::forceContentSniffing();
842
843 #if USE(GLIB)
844     [self _scheduleGlibContextIterations];
845 #endif
846 }
847
848 - (id)_initWithFrame:(NSRect)f frameName:(NSString *)frameName groupName:(NSString *)groupName usesDocumentViews:(BOOL)usesDocumentViews
849 {
850     // FIXME: Remove the usesDocumentViews parameter; it's only here for compatibility with WebKit nightly builds
851     // running against Safari 5 on Leopard.
852     ASSERT(usesDocumentViews);
853
854     self = [super initWithFrame:f];
855     if (!self)
856         return nil;
857
858 #ifdef ENABLE_WEBKIT_UNSET_DYLD_FRAMEWORK_PATH
859     // DYLD_FRAMEWORK_PATH is used so Safari will load the development version of WebKit, which
860     // may not work with other WebKit applications.  Unsetting DYLD_FRAMEWORK_PATH removes the
861     // need for Safari to unset it to prevent it from being passed to applications it launches.
862     // Unsetting it when a WebView is first created is as good a place as any.
863     // See <http://bugs.webkit.org/show_bug.cgi?id=4286> for more details.
864     if (getenv("WEBKIT_UNSET_DYLD_FRAMEWORK_PATH")) {
865         unsetenv("DYLD_FRAMEWORK_PATH");
866         unsetenv("WEBKIT_UNSET_DYLD_FRAMEWORK_PATH");
867     }
868 #endif
869
870     _private = [[WebViewPrivate alloc] init];
871     [self _commonInitializationWithFrameName:frameName groupName:groupName];
872     [self setMaintainsBackForwardList: YES];
873     _private->page->setDeviceScaleFactor([self _deviceScaleFactor]);
874     return self;
875 }
876
877 - (void)_viewWillDrawInternal
878 {
879     Frame* frame = [self _mainCoreFrame];
880     if (frame && frame->view())
881         frame->view()->updateLayoutAndStyleIfNeededRecursive();
882 }
883
884 + (NSArray *)_supportedMIMETypes
885 {
886     // Load the plug-in DB allowing plug-ins to install types.
887     [WebPluginDatabase sharedDatabase];
888     return [[WebFrameView _viewTypesAllowImageTypeOmission:NO] allKeys];
889 }
890
891 + (NSArray *)_supportedFileExtensions
892 {
893     NSMutableSet *extensions = [[NSMutableSet alloc] init];
894     NSArray *MIMETypes = [self _supportedMIMETypes];
895     NSEnumerator *enumerator = [MIMETypes objectEnumerator];
896     NSString *MIMEType;
897     while ((MIMEType = [enumerator nextObject]) != nil) {
898         NSArray *extensionsForType = WKGetExtensionsForMIMEType(MIMEType);
899         if (extensionsForType) {
900             [extensions addObjectsFromArray:extensionsForType];
901         }
902     }
903     NSArray *uniqueExtensions = [extensions allObjects];
904     [extensions release];
905     return uniqueExtensions;
906 }
907
908 static NSMutableSet *knownPluginMIMETypes()
909 {
910     static NSMutableSet *mimeTypes = [[NSMutableSet alloc] init];
911     
912     return mimeTypes;
913 }
914
915 + (void)_registerPluginMIMEType:(NSString *)MIMEType
916 {
917     [WebView registerViewClass:[WebHTMLView class] representationClass:[WebHTMLRepresentation class] forMIMEType:MIMEType];
918     [knownPluginMIMETypes() addObject:MIMEType];
919 }
920
921 + (void)_unregisterPluginMIMEType:(NSString *)MIMEType
922 {
923     [self _unregisterViewClassAndRepresentationClassForMIMEType:MIMEType];
924     [knownPluginMIMETypes() removeObject:MIMEType];
925 }
926
927 + (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType allowingPlugins:(BOOL)allowPlugins
928 {
929     MIMEType = [MIMEType lowercaseString];
930     Class viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:YES] _webkit_objectForMIMEType:MIMEType];
931     Class repClass = [[WebDataSource _repTypesAllowImageTypeOmission:YES] _webkit_objectForMIMEType:MIMEType];
932
933     if (!viewClass || !repClass || [[WebPDFView supportedMIMETypes] containsObject:MIMEType]) {
934         // Our optimization to avoid loading the plug-in DB and image types for the HTML case failed.
935
936         if (allowPlugins) {
937             // Load the plug-in DB allowing plug-ins to install types.
938             [WebPluginDatabase sharedDatabase];
939         }
940
941         // Load the image types and get the view class and rep class. This should be the fullest picture of all handled types.
942         viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:NO] _webkit_objectForMIMEType:MIMEType];
943         repClass = [[WebDataSource _repTypesAllowImageTypeOmission:NO] _webkit_objectForMIMEType:MIMEType];
944     }
945     
946     if (viewClass && repClass) {
947         if (viewClass == [WebHTMLView class] && repClass == [WebHTMLRepresentation class]) {
948             // Special-case WebHTMLView for text types that shouldn't be shown.
949             if ([[WebHTMLView unsupportedTextMIMETypes] containsObject:MIMEType])
950                 return NO;
951
952             // If the MIME type is a known plug-in we might not want to load it.
953             if (!allowPlugins && [knownPluginMIMETypes() containsObject:MIMEType]) {
954                 BOOL isSupportedByWebKit = [[WebHTMLView supportedNonImageMIMETypes] containsObject:MIMEType] ||
955                     [[WebHTMLView supportedMIMETypes] containsObject:MIMEType];
956                 
957                 // If this is a known plug-in MIME type and WebKit can't show it natively, we don't want to show it.
958                 if (!isSupportedByWebKit)
959                     return NO;
960             }
961         }
962         if (vClass)
963             *vClass = viewClass;
964         if (rClass)
965             *rClass = repClass;
966         return YES;
967     }
968     
969     return NO;
970 }
971
972 - (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType
973 {
974     if ([[self class] _viewClass:vClass andRepresentationClass:rClass forMIMEType:MIMEType allowingPlugins:[_private->preferences arePlugInsEnabled]])
975         return YES;
976
977     if (_private->pluginDatabase) {
978         WebBasePluginPackage *pluginPackage = [_private->pluginDatabase pluginForMIMEType:MIMEType];
979         if (pluginPackage) {
980             if (vClass)
981                 *vClass = [WebHTMLView class];
982             if (rClass)
983                 *rClass = [WebHTMLRepresentation class];
984             return YES;
985         }
986     }
987     
988     return NO;
989 }
990
991 + (void)_setAlwaysUseATSU:(BOOL)f
992 {
993     [self _setAlwaysUsesComplexTextCodePath:f];
994 }
995
996 + (void)_setAlwaysUsesComplexTextCodePath:(BOOL)f
997 {
998     Font::setCodePath(f ? Font::Complex : Font::Auto);
999 }
1000
1001 + (void)_setAllowsRoundingHacks:(BOOL)allowsRoundingHacks
1002 {
1003     TextRun::setAllowsRoundingHacks(allowsRoundingHacks);
1004 }
1005
1006 + (BOOL)_allowsRoundingHacks
1007 {
1008     return TextRun::allowsRoundingHacks();
1009 }
1010
1011 + (BOOL)canCloseAllWebViews
1012 {
1013     return DOMWindow::dispatchAllPendingBeforeUnloadEvents();
1014 }
1015
1016 + (void)closeAllWebViews
1017 {
1018     DOMWindow::dispatchAllPendingUnloadEvents();
1019
1020     // This will close the WebViews in a random order. Change this if close order is important.
1021     // Make a new set to avoid mutating the set we are enumerating.
1022     NSSet *webViewsToClose = [NSSet setWithSet:(NSSet *)allWebViewsSet]; 
1023     NSEnumerator *enumerator = [webViewsToClose objectEnumerator];
1024     while (WebView *webView = [enumerator nextObject])
1025         [webView close];
1026 }
1027
1028 + (BOOL)canShowFile:(NSString *)path
1029 {
1030     return [[self class] canShowMIMEType:[WebView _MIMETypeForFile:path]];
1031 }
1032
1033 + (NSString *)suggestedFileExtensionForMIMEType:(NSString *)type
1034 {
1035     return WKGetPreferredExtensionForMIMEType(type);
1036 }
1037
1038 - (BOOL)_isClosed
1039 {
1040     return !_private || _private->closed;
1041 }
1042
1043 - (void)_closePluginDatabases
1044 {
1045     pluginDatabaseClientCount--;
1046
1047     // Close both sets of plug-in databases because plug-ins need an opportunity to clean up files, etc.
1048
1049     // Unload the WebView local plug-in database. 
1050     if (_private->pluginDatabase) {
1051         [_private->pluginDatabase destroyAllPluginInstanceViews];
1052         [_private->pluginDatabase close];
1053         [_private->pluginDatabase release];
1054         _private->pluginDatabase = nil;
1055     }
1056     
1057     // Keep the global plug-in database active until the app terminates to avoid having to reload plug-in bundles.
1058     if (!pluginDatabaseClientCount && applicationIsTerminating)
1059         [WebPluginDatabase closeSharedDatabase];
1060 }
1061
1062 - (void)_closeWithFastTeardown 
1063 {
1064 #ifndef NDEBUG
1065     WTF::RefCountedLeakCounter::suppressMessages("At least one WebView was closed with fast teardown.");
1066 #endif
1067
1068     [[NSDistributedNotificationCenter defaultCenter] removeObserver:self];
1069     [[NSNotificationCenter defaultCenter] removeObserver:self];
1070
1071     [self _closePluginDatabases];
1072 }
1073
1074 static bool fastDocumentTeardownEnabled()
1075 {
1076 #ifdef NDEBUG
1077     static bool enabled = ![[NSUserDefaults standardUserDefaults] boolForKey:WebKitEnableFullDocumentTeardownPreferenceKey];
1078 #else
1079     static bool initialized = false;
1080     static bool enabled = false;
1081     if (!initialized) {
1082         // This allows debug builds to default to not have fast teardown, so leak checking still works.
1083         // But still allow the WebKitEnableFullDocumentTeardown default to override it if present.
1084         NSNumber *setting = [[NSUserDefaults standardUserDefaults] objectForKey:WebKitEnableFullDocumentTeardownPreferenceKey];
1085         if (setting)
1086             enabled = ![setting boolValue];
1087         initialized = true;
1088     }
1089 #endif
1090     return enabled;
1091 }
1092
1093 // _close is here only for backward compatibility; clients and subclasses should use
1094 // public method -close instead.
1095 - (void)_close
1096 {
1097     if (!_private || _private->closed)
1098         return;
1099
1100     [[NSNotificationCenter defaultCenter] postNotificationName:WebViewWillCloseNotification object:self];
1101
1102     _private->closed = YES;
1103     [self _removeFromAllWebViewsSet];
1104
1105 #ifndef NDEBUG
1106     WTF::RefCountedLeakCounter::cancelMessageSuppression(webViewIsOpen);
1107 #endif
1108
1109     // To quit the apps fast we skip document teardown, except plugins
1110     // need to be destroyed and unloaded.
1111     if (applicationIsTerminating && fastDocumentTeardownEnabled()) {
1112         [self _closeWithFastTeardown];
1113         return;
1114     }
1115
1116 #if ENABLE(VIDEO)
1117     [self _exitFullscreen];
1118 #endif
1119
1120     if (Frame* mainFrame = [self _mainCoreFrame])
1121         mainFrame->loader().detachFromParent();
1122
1123     [self setHostWindow:nil];
1124
1125     [self setDownloadDelegate:nil];
1126     [self setEditingDelegate:nil];
1127     [self setFrameLoadDelegate:nil];
1128     [self setPolicyDelegate:nil];
1129     [self setResourceLoadDelegate:nil];
1130     [self setScriptDebugDelegate:nil];
1131     [self setUIDelegate:nil];
1132
1133     [_private->inspector webViewClosed];
1134
1135     // To avoid leaks, call removeDragCaret in case it wasn't called after moveDragCaretToPoint.
1136     [self removeDragCaret];
1137
1138     // Deleteing the WebCore::Page will clear the page cache so we call destroy on 
1139     // all the plug-ins in the page cache to break any retain cycles.
1140     // See comment in HistoryItem::releaseAllPendingPageCaches() for more information.
1141     Page* page = _private->page;
1142     _private->page = 0;
1143     delete page;
1144
1145     if (_private->hasSpellCheckerDocumentTag) {
1146         [[NSSpellChecker sharedSpellChecker] closeSpellDocumentWithTag:_private->spellCheckerDocumentTag];
1147         _private->hasSpellCheckerDocumentTag = NO;
1148     }
1149
1150 #if USE(ACCELERATED_COMPOSITING)
1151     if (_private->layerFlushController) {
1152         _private->layerFlushController->invalidate();
1153         _private->layerFlushController = nullptr;
1154     }
1155 #endif
1156     
1157 #if USE(GLIB)
1158     [self _clearGlibLoopObserver];
1159 #endif
1160
1161     [[self _notificationProvider] unregisterWebView:self];
1162
1163     [[NSDistributedNotificationCenter defaultCenter] removeObserver:self];
1164     [[NSNotificationCenter defaultCenter] removeObserver:self];
1165
1166     [WebPreferences _removeReferenceForIdentifier:[self preferencesIdentifier]];
1167
1168     WebPreferences *preferences = _private->preferences;
1169     _private->preferences = nil;
1170     [preferences didRemoveFromWebView];
1171     [preferences release];
1172
1173     [self _closePluginDatabases];
1174
1175 #ifndef NDEBUG
1176     // Need this to make leak messages accurate.
1177     if (applicationIsTerminating) {
1178         gcController().garbageCollectNow();
1179         [WebCache setDisabled:YES];
1180     }
1181 #endif
1182 }
1183
1184 // Indicates if the WebView is in the midst of a user gesture.
1185 - (BOOL)_isProcessingUserGesture
1186 {
1187     return ScriptController::processingUserGesture();
1188 }
1189
1190 + (NSString *)_MIMETypeForFile:(NSString *)path
1191 {
1192     NSString *extension = [path pathExtension];
1193     NSString *MIMEType = nil;
1194
1195     // Get the MIME type from the extension.
1196     if ([extension length] != 0) {
1197         MIMEType = WKGetMIMETypeForExtension(extension);
1198     }
1199
1200     // If we can't get a known MIME type from the extension, sniff.
1201     if ([MIMEType length] == 0 || [MIMEType isEqualToString:@"application/octet-stream"]) {
1202         NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:path];
1203         NSData *data = [handle readDataOfLength:WEB_GUESS_MIME_TYPE_PEEK_LENGTH];
1204         [handle closeFile];
1205         if ([data length] != 0) {
1206             MIMEType = [data _webkit_guessedMIMEType];
1207         }
1208         if ([MIMEType length] == 0) {
1209             MIMEType = @"application/octet-stream";
1210         }
1211     }
1212
1213     return MIMEType;
1214 }
1215
1216 - (WebDownload *)_downloadURL:(NSURL *)URL
1217 {
1218     ASSERT(URL);
1219     
1220     NSURLRequest *request = [[NSURLRequest alloc] initWithURL:URL];
1221     WebDownload *download = [WebDownload _downloadWithRequest:request
1222                                                      delegate:_private->downloadDelegate
1223                                                     directory:nil];
1224     [request release];
1225     
1226     return download;
1227 }
1228
1229 - (WebView *)_openNewWindowWithRequest:(NSURLRequest *)request
1230 {
1231     NSDictionary *features = [[NSDictionary alloc] init];
1232     WebView *newWindowWebView = [[self _UIDelegateForwarder] webView:self
1233                                             createWebViewWithRequest:nil
1234                                                       windowFeatures:features];
1235     [features release];
1236     if (!newWindowWebView)
1237         return nil;
1238
1239     CallUIDelegate(newWindowWebView, @selector(webViewShow:));
1240     return newWindowWebView;
1241 }
1242
1243 - (WebInspector *)inspector
1244 {
1245     if (!_private->inspector)
1246         _private->inspector = [[WebInspector alloc] initWithWebView:self];
1247     return _private->inspector;
1248 }
1249
1250 - (WebCore::Page*)page
1251 {
1252     return _private->page;
1253 }
1254
1255 - (NSMenu *)_menuForElement:(NSDictionary *)element defaultItems:(NSArray *)items
1256 {
1257     NSArray *defaultMenuItems = [[WebDefaultUIDelegate sharedUIDelegate] webView:self contextMenuItemsForElement:element defaultMenuItems:items];
1258     NSArray *menuItems = defaultMenuItems;
1259
1260     // CallUIDelegate returns nil if UIDelegate is nil or doesn't respond to the selector. So we need to check that here
1261     // to distinguish between using defaultMenuItems or the delegate really returning nil to say "no context menu".
1262     SEL selector = @selector(webView:contextMenuItemsForElement:defaultMenuItems:);
1263     if (_private->UIDelegate && [_private->UIDelegate respondsToSelector:selector]) {
1264         menuItems = CallUIDelegate(self, selector, element, defaultMenuItems);
1265         if (!menuItems)
1266             return nil;
1267     }
1268
1269     unsigned count = [menuItems count];
1270     if (!count)
1271         return nil;
1272
1273     NSMenu *menu = [[NSMenu alloc] init];
1274     for (unsigned i = 0; i < count; i++)
1275         [menu addItem:[menuItems objectAtIndex:i]];
1276
1277     return [menu autorelease];
1278 }
1279
1280 - (void)_mouseDidMoveOverElement:(NSDictionary *)dictionary modifierFlags:(NSUInteger)modifierFlags
1281 {
1282     // We originally intended to call this delegate method sometimes with a nil dictionary, but due to
1283     // a bug dating back to WebKit 1.0 this delegate was never called with nil! Unfortunately we can't
1284     // start calling this with nil since it will break Adobe Help Viewer, and possibly other clients.
1285     if (!dictionary)
1286         return;
1287     CallUIDelegate(self, @selector(webView:mouseDidMoveOverElement:modifierFlags:), dictionary, modifierFlags);
1288 }
1289
1290 - (void)_loadBackForwardListFromOtherView:(WebView *)otherView
1291 {
1292     if (!_private->page)
1293         return;
1294     
1295     if (!otherView->_private->page)
1296         return;
1297     
1298     // It turns out the right combination of behavior is done with the back/forward load
1299     // type.  (See behavior matrix at the top of WebFramePrivate.)  So we copy all the items
1300     // in the back forward list, and go to the current one.
1301
1302     BackForwardClient* backForwardClient = _private->page->backForwardClient();
1303     ASSERT(!backForwardClient->currentItem()); // destination list should be empty
1304
1305     BackForwardClient* otherBackForwardClient = otherView->_private->page->backForwardClient();
1306     if (!otherBackForwardClient->currentItem())
1307         return; // empty back forward list, bail
1308     
1309     HistoryItem* newItemToGoTo = 0;
1310
1311     int lastItemIndex = otherBackForwardClient->forwardListCount();
1312     for (int i = -otherBackForwardClient->backListCount(); i <= lastItemIndex; ++i) {
1313         if (i == 0) {
1314             // If this item is showing , save away its current scroll and form state,
1315             // since that might have changed since loading and it is normally not saved
1316             // until we leave that page.
1317             otherView->_private->page->mainFrame().loader().history().saveDocumentAndScrollState();
1318         }
1319         RefPtr<HistoryItem> newItem = otherBackForwardClient->itemAtIndex(i)->copy();
1320         if (i == 0) 
1321             newItemToGoTo = newItem.get();
1322         backForwardClient->addItem(newItem.release());
1323     }
1324     
1325     ASSERT(newItemToGoTo);
1326     _private->page->goToItem(newItemToGoTo, FrameLoadTypeIndexedBackForward);
1327 }
1328
1329 - (void)_setFormDelegate: (id<WebFormDelegate>)delegate
1330 {
1331     _private->formDelegate = delegate;
1332 }
1333
1334 - (id<WebFormDelegate>)_formDelegate
1335 {
1336     return _private->formDelegate;
1337 }
1338
1339 - (BOOL)_needsAdobeFrameReloadingQuirk
1340 {
1341     static BOOL needsQuirk = WKAppVersionCheckLessThan(@"com.adobe.Acrobat", -1, 9.0)
1342         || WKAppVersionCheckLessThan(@"com.adobe.Acrobat.Pro", -1, 9.0)
1343         || WKAppVersionCheckLessThan(@"com.adobe.Reader", -1, 9.0)
1344         || WKAppVersionCheckLessThan(@"com.adobe.distiller", -1, 9.0)
1345         || WKAppVersionCheckLessThan(@"com.adobe.Contribute", -1, 4.2)
1346         || WKAppVersionCheckLessThan(@"com.adobe.dreamweaver-9.0", -1, 9.1)
1347         || WKAppVersionCheckLessThan(@"com.macromedia.fireworks", -1, 9.1)
1348         || WKAppVersionCheckLessThan(@"com.adobe.InCopy", -1, 5.1)
1349         || WKAppVersionCheckLessThan(@"com.adobe.InDesign", -1, 5.1)
1350         || WKAppVersionCheckLessThan(@"com.adobe.Soundbooth", -1, 2);
1351
1352     return needsQuirk;
1353 }
1354
1355 - (BOOL)_needsLinkElementTextCSSQuirk
1356 {
1357     static BOOL needsQuirk = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_LINK_ELEMENT_TEXT_CSS_QUIRK)
1358         && WKAppVersionCheckLessThan(@"com.e-frontier.shade10", -1, 10.6);
1359     return needsQuirk;
1360 }
1361
1362 - (BOOL)_needsIsLoadingInAPISenseQuirk
1363 {
1364     static BOOL needsQuirk = WKAppVersionCheckLessThan(@"com.apple.iAdProducer", -1, 2.1);
1365     
1366     return needsQuirk;
1367 }
1368
1369 - (BOOL)_needsKeyboardEventDisambiguationQuirks
1370 {
1371     static BOOL needsQuirks = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_IE_COMPATIBLE_KEYBOARD_EVENT_DISPATCH) && !applicationIsSafari();
1372     return needsQuirks;
1373 }
1374
1375 - (BOOL)_needsFrameLoadDelegateRetainQuirk
1376 {
1377     static BOOL needsQuirk = WKAppVersionCheckLessThan(@"com.equinux.iSale5", -1, 5.6);    
1378     return needsQuirk;
1379 }
1380
1381 static bool needsSelfRetainWhileLoadingQuirk()
1382 {
1383     static bool needsQuirk = applicationIsAperture();
1384     return needsQuirk;
1385 }
1386
1387 - (BOOL)_needsPreHTML5ParserQuirks
1388 {    
1389     // AOL Instant Messenger and Microsoft My Day contain markup incompatible
1390     // with the new HTML5 parser. If these applications were linked against a
1391     // version of WebKit prior to the introduction of the HTML5 parser, enable
1392     // parser quirks to maintain compatibility. For details, see 
1393     // <https://bugs.webkit.org/show_bug.cgi?id=46134> and
1394     // <https://bugs.webkit.org/show_bug.cgi?id=46334>.
1395     static bool isApplicationNeedingParserQuirks = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_HTML5_PARSER)
1396         && (applicationIsAOLInstantMessenger() || applicationIsMicrosoftMyDay());
1397     
1398     // Mail.app must continue to display HTML email that contains quirky markup.
1399     static bool isAppleMail = applicationIsAppleMail();
1400
1401     return isApplicationNeedingParserQuirks
1402         || isAppleMail
1403 #if ENABLE(DASHBOARD_SUPPORT)
1404         // Pre-HTML5 parser quirks are required to remain compatible with many
1405         // Dashboard widgets. See <rdar://problem/8175982>.
1406         || (_private->page && _private->page->settings().usesDashboardBackwardCompatibilityMode())
1407 #endif
1408         || [[self preferences] usePreHTML5ParserQuirks];
1409 }
1410
1411 - (BOOL)_needsUnrestrictedGetMatchedCSSRules
1412 {
1413     static bool needsUnrestrictedGetMatchedCSSRules = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_GET_MATCHED_CSS_RULES_RESTRICTIONS) && applicationIsSafari();
1414     return needsUnrestrictedGetMatchedCSSRules;
1415 }
1416
1417 - (void)_preferencesChangedNotification:(NSNotification *)notification
1418 {
1419     WebPreferences *preferences = (WebPreferences *)[notification object];
1420     [self _preferencesChanged:preferences];
1421 }
1422
1423 - (void)_preferencesChanged:(WebPreferences *)preferences
1424 {    
1425     ASSERT(preferences == [self preferences]);
1426     if (!_private->userAgentOverridden)
1427         _private->userAgent = String();
1428
1429     // Cache this value so we don't have to read NSUserDefaults on each page load
1430     _private->useSiteSpecificSpoofing = [preferences _useSiteSpecificSpoofing];
1431
1432     // Update corresponding WebCore Settings object.
1433     if (!_private->page)
1434         return;
1435     
1436     Settings& settings = _private->page->settings();
1437
1438     settings.setCursiveFontFamily([preferences cursiveFontFamily]);
1439     settings.setDefaultFixedFontSize([preferences defaultFixedFontSize]);
1440     settings.setDefaultFontSize([preferences defaultFontSize]);
1441     settings.setDefaultTextEncodingName([preferences defaultTextEncodingName]);
1442     settings.setUsesEncodingDetector([preferences usesEncodingDetector]);
1443     settings.setFantasyFontFamily([preferences fantasyFontFamily]);
1444     settings.setFixedFontFamily([preferences fixedFontFamily]);
1445     settings.setScreenFontSubstitutionEnabled(
1446 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
1447         [[NSUserDefaults standardUserDefaults] boolForKey:@"NSFontDefaultScreenFontSubstitutionEnabled"] ||
1448 #endif
1449         [preferences screenFontSubstitutionEnabled]
1450     );
1451     settings.setForceFTPDirectoryListings([preferences _forceFTPDirectoryListings]);
1452     settings.setFTPDirectoryTemplatePath([preferences _ftpDirectoryTemplatePath]);
1453     settings.setLocalStorageDatabasePath([preferences _localStorageDatabasePath]);
1454     settings.setJavaEnabled([preferences isJavaEnabled]);
1455     settings.setScriptEnabled([preferences isJavaScriptEnabled]);
1456     settings.setWebSecurityEnabled([preferences isWebSecurityEnabled]);
1457     settings.setAllowUniversalAccessFromFileURLs([preferences allowUniversalAccessFromFileURLs]);
1458     settings.setAllowFileAccessFromFileURLs([preferences allowFileAccessFromFileURLs]);
1459     settings.setJavaScriptCanOpenWindowsAutomatically([preferences javaScriptCanOpenWindowsAutomatically]);
1460     settings.setMinimumFontSize([preferences minimumFontSize]);
1461     settings.setMinimumLogicalFontSize([preferences minimumLogicalFontSize]);
1462     settings.setPictographFontFamily([preferences pictographFontFamily]);
1463     settings.setPluginsEnabled([preferences arePlugInsEnabled]);
1464 #if ENABLE(SQL_DATABASE)
1465     DatabaseManager::manager().setIsAvailable([preferences databasesEnabled]);
1466 #endif
1467     settings.setLocalStorageEnabled([preferences localStorageEnabled]);
1468     settings.setExperimentalNotificationsEnabled([preferences experimentalNotificationsEnabled]);
1469
1470     bool privateBrowsingEnabled = [preferences privateBrowsingEnabled];
1471 #if PLATFORM(MAC) || USE(CFNETWORK)
1472     if (privateBrowsingEnabled)
1473         WebFrameNetworkingContext::ensurePrivateBrowsingSession();
1474     else
1475         WebFrameNetworkingContext::destroyPrivateBrowsingSession();
1476 #endif
1477     settings.setPrivateBrowsingEnabled(privateBrowsingEnabled);
1478
1479     settings.setSansSerifFontFamily([preferences sansSerifFontFamily]);
1480     settings.setSerifFontFamily([preferences serifFontFamily]);
1481     settings.setStandardFontFamily([preferences standardFontFamily]);
1482     settings.setLoadsImagesAutomatically([preferences loadsImagesAutomatically]);
1483     settings.setLoadsSiteIconsIgnoringImageLoadingSetting([preferences loadsSiteIconsIgnoringImageLoadingPreference]);
1484     settings.setShouldPrintBackgrounds([preferences shouldPrintBackgrounds]);
1485     settings.setTextAreasAreResizable([preferences textAreasAreResizable]);
1486     settings.setShrinksStandaloneImagesToFit([preferences shrinksStandaloneImagesToFit]);
1487     settings.setEditableLinkBehavior(core([preferences editableLinkBehavior]));
1488     settings.setTextDirectionSubmenuInclusionBehavior(core([preferences textDirectionSubmenuInclusionBehavior]));
1489     settings.setDOMPasteAllowed([preferences isDOMPasteAllowed]);
1490     settings.setUsesPageCache([self usesPageCache]);
1491     settings.setPageCacheSupportsPlugins([preferences pageCacheSupportsPlugins]);
1492     settings.setBackForwardCacheExpirationInterval([preferences _backForwardCacheExpirationInterval]);
1493     settings.setShowsURLsInToolTips([preferences showsURLsInToolTips]);
1494     settings.setShowsToolTipOverTruncatedText([preferences showsToolTipOverTruncatedText]);
1495     settings.setDeveloperExtrasEnabled([preferences developerExtrasEnabled]);
1496     settings.setJavaScriptExperimentsEnabled([preferences javaScriptExperimentsEnabled]);
1497     settings.setAuthorAndUserStylesEnabled([preferences authorAndUserStylesEnabled]);
1498     settings.setApplicationChromeMode([preferences applicationChromeModeEnabled]);
1499     if ([preferences userStyleSheetEnabled]) {
1500         NSString* location = [[preferences userStyleSheetLocation] _web_originalDataAsString];
1501         if ([location isEqualToString:@"apple-dashboard://stylesheet"])
1502             location = @"file:///System/Library/PrivateFrameworks/DashboardClient.framework/Resources/widget.css";
1503         settings.setUserStyleSheetLocation([NSURL URLWithString:(location ? location : @"")]);
1504     } else
1505         settings.setUserStyleSheetLocation([NSURL URLWithString:@""]);
1506     settings.setNeedsAdobeFrameReloadingQuirk([self _needsAdobeFrameReloadingQuirk]);
1507     settings.setTreatsAnyTextCSSLinkAsStylesheet([self _needsLinkElementTextCSSQuirk]);
1508     settings.setNeedsKeyboardEventDisambiguationQuirks([self _needsKeyboardEventDisambiguationQuirks]);
1509     settings.setNeedsSiteSpecificQuirks(_private->useSiteSpecificSpoofing);
1510     settings.setWebArchiveDebugModeEnabled([preferences webArchiveDebugModeEnabled]);
1511     settings.setLocalFileContentSniffingEnabled([preferences localFileContentSniffingEnabled]);
1512     settings.setOfflineWebApplicationCacheEnabled([preferences offlineWebApplicationCacheEnabled]);
1513     settings.setJavaScriptCanAccessClipboard([preferences javaScriptCanAccessClipboard]);
1514     settings.setXSSAuditorEnabled([preferences isXSSAuditorEnabled]);
1515     settings.setEnforceCSSMIMETypeInNoQuirksMode(!WKAppVersionCheckLessThan(@"com.apple.iWeb", -1, 2.1));
1516     settings.setDNSPrefetchingEnabled([preferences isDNSPrefetchingEnabled]);
1517     
1518     // FIXME: Enabling accelerated compositing when WebGL is enabled causes tests to fail on Leopard which expect HW compositing to be disabled.
1519     // Until we fix that, I will comment out the test (CFM)
1520     settings.setAcceleratedCompositingEnabled([preferences acceleratedCompositingEnabled]);
1521     settings.setAcceleratedDrawingEnabled([preferences acceleratedDrawingEnabled]);
1522     settings.setCanvasUsesAcceleratedDrawing([preferences canvasUsesAcceleratedDrawing]);    
1523     settings.setShowDebugBorders([preferences showDebugBorders]);
1524     settings.setShowRepaintCounter([preferences showRepaintCounter]);
1525     settings.setWebGLEnabled([preferences webGLEnabled]);
1526     settings.setMultithreadedWebGLEnabled([preferences multithreadedWebGLEnabled]);
1527     settings.setAccelerated2dCanvasEnabled([preferences accelerated2dCanvasEnabled]);
1528     settings.setLoadDeferringEnabled(shouldEnableLoadDeferring());
1529     settings.setWindowFocusRestricted(shouldRestrictWindowFocus());
1530     settings.setFrameFlatteningEnabled([preferences isFrameFlatteningEnabled]);
1531     settings.setSpatialNavigationEnabled([preferences isSpatialNavigationEnabled]);
1532     settings.setPaginateDuringLayoutEnabled([preferences paginateDuringLayoutEnabled]);
1533 #if ENABLE(CSS_SHADERS)
1534     settings.setCSSCustomFilterEnabled([preferences cssCustomFilterEnabled]);
1535 #endif
1536     RuntimeEnabledFeatures::sharedFeatures().setCSSRegionsEnabled([preferences cssRegionsEnabled]);
1537     RuntimeEnabledFeatures::sharedFeatures().setCSSCompositingEnabled([preferences cssCompositingEnabled]);
1538 #if ENABLE(WEB_AUDIO)
1539     settings.setWebAudioEnabled([preferences webAudioEnabled]);
1540 #endif
1541 #if ENABLE(IFRAME_SEAMLESS)
1542     RuntimeEnabledFeatures::sharedFeatures().setSeamlessIFramesEnabled([preferences seamlessIFramesEnabled]);
1543 #endif
1544     settings.setCSSGridLayoutEnabled([preferences cssGridLayoutEnabled]);
1545 #if ENABLE(FULLSCREEN_API)
1546     settings.setFullScreenEnabled([preferences fullScreenEnabled]);
1547 #endif
1548     settings.setAsynchronousSpellCheckingEnabled([preferences asynchronousSpellCheckingEnabled]);
1549     settings.setHyperlinkAuditingEnabled([preferences hyperlinkAuditingEnabled]);
1550     settings.setUsePreHTML5ParserQuirks([self _needsPreHTML5ParserQuirks]);
1551     settings.setCrossOriginCheckInGetMatchedCSSRulesDisabled([self _needsUnrestrictedGetMatchedCSSRules]);
1552     settings.setInteractiveFormValidationEnabled([self interactiveFormValidationEnabled]);
1553     settings.setValidationMessageTimerMagnification([self validationMessageTimerMagnification]);
1554 #if USE(AVFOUNDATION)
1555     settings.setAVFoundationEnabled([preferences isAVFoundationEnabled]);
1556 #endif
1557 #if PLATFORM(MAC)
1558     settings.setQTKitEnabled([preferences isQTKitEnabled]);
1559 #endif
1560     settings.setMediaPlaybackRequiresUserGesture([preferences mediaPlaybackRequiresUserGesture]);
1561     settings.setMediaPlaybackAllowsInline([preferences mediaPlaybackAllowsInline]);
1562     settings.setSuppressesIncrementalRendering([preferences suppressesIncrementalRendering]);
1563     settings.setRegionBasedColumnsEnabled([preferences regionBasedColumnsEnabled]);
1564     settings.setBackspaceKeyNavigationEnabled([preferences backspaceKeyNavigationEnabled]);
1565     settings.setWantsBalancedSetDefersLoadingBehavior([preferences wantsBalancedSetDefersLoadingBehavior]);
1566     settings.setMockScrollbarsEnabled([preferences mockScrollbarsEnabled]);
1567
1568 #if ENABLE(VIDEO_TRACK)
1569     settings.setShouldDisplaySubtitles([preferences shouldDisplaySubtitles]);
1570     settings.setShouldDisplayCaptions([preferences shouldDisplayCaptions]);
1571     settings.setShouldDisplayTextDescriptions([preferences shouldDisplayTextDescriptions]);
1572 #endif
1573
1574     settings.setShouldRespectImageOrientation([preferences shouldRespectImageOrientation]);
1575     settings.setNeedsIsLoadingInAPISenseQuirk([self _needsIsLoadingInAPISenseQuirk]);
1576     settings.setRequestAnimationFrameEnabled([preferences requestAnimationFrameEnabled]);
1577     settings.setDiagnosticLoggingEnabled([preferences diagnosticLoggingEnabled]);
1578     settings.setLowPowerVideoAudioBufferSizeEnabled([preferences lowPowerVideoAudioBufferSizeEnabled]);
1579
1580     switch ([preferences storageBlockingPolicy]) {
1581     case WebAllowAllStorage:
1582         settings.setStorageBlockingPolicy(SecurityOrigin::AllowAllStorage);
1583         break;
1584     case WebBlockThirdPartyStorage:
1585         settings.setStorageBlockingPolicy(SecurityOrigin::BlockThirdPartyStorage);
1586         break;
1587     case WebBlockAllStorage:
1588         settings.setStorageBlockingPolicy(SecurityOrigin::BlockAllStorage);
1589         break;
1590     }
1591
1592     settings.setPlugInSnapshottingEnabled([preferences plugInSnapshottingEnabled]);
1593
1594 #if ENABLE(HIDDEN_PAGE_DOM_TIMER_THROTTLING)
1595     settings.setHiddenPageDOMTimerThrottlingEnabled([preferences hiddenPageDOMTimerThrottlingEnabled]);
1596 #endif
1597 #if ENABLE(PAGE_VISIBILITY_API)
1598     settings.setHiddenPageCSSAnimationSuspensionEnabled([preferences hiddenPageCSSAnimationSuspensionEnabled]);
1599 #endif
1600
1601     // We have enabled this setting in WebKit2 for the sake of some ScrollingCoordinator work.
1602     // To avoid possible rendering differences, we should enable it for WebKit1 too.
1603     settings.setFixedPositionCreatesStackingContext(true);
1604     
1605     NSTimeInterval timeout = [preferences incrementalRenderingSuppressionTimeoutInSeconds];
1606     if (timeout > 0)
1607         settings.setIncrementalRenderingSuppressionTimeoutInSeconds(timeout);
1608
1609     // Application Cache Preferences are stored on the global cache storage manager, not in Settings.
1610     [WebApplicationCache setDefaultOriginQuota:[preferences applicationCacheDefaultOriginQuota]];
1611
1612     BOOL zoomsTextOnly = [preferences zoomsTextOnly];
1613     if (_private->zoomsTextOnly != zoomsTextOnly)
1614         [self _setZoomMultiplier:_private->zoomMultiplier isTextOnly:zoomsTextOnly];
1615
1616 #if ENABLE(DISK_IMAGE_CACHE) && PLATFORM(IOS)
1617     DiskImageCache& diskImageCache = WebCore::diskImageCache();
1618     diskImageCache.setEnabled([preferences diskImageCacheEnabled]);
1619     diskImageCache.setMinimumImageSize([preferences diskImageCacheMinimumImageSize]);
1620     diskImageCache.setMaximumCacheSize([preferences diskImageCacheMaximumCacheSize]);
1621 #endif
1622 }
1623
1624 static inline IMP getMethod(id o, SEL s)
1625 {
1626     return [o respondsToSelector:s] ? [o methodForSelector:s] : 0;
1627 }
1628
1629 - (void)_cacheResourceLoadDelegateImplementations
1630 {
1631     WebResourceDelegateImplementationCache *cache = &_private->resourceLoadDelegateImplementations;
1632     id delegate = _private->resourceProgressDelegate;
1633
1634     if (!delegate) {
1635         bzero(cache, sizeof(WebResourceDelegateImplementationCache));
1636         return;
1637     }
1638
1639     cache->didCancelAuthenticationChallengeFunc = getMethod(delegate, @selector(webView:resource:didCancelAuthenticationChallenge:fromDataSource:));
1640     cache->didFailLoadingWithErrorFromDataSourceFunc = getMethod(delegate, @selector(webView:resource:didFailLoadingWithError:fromDataSource:));
1641     cache->didFinishLoadingFromDataSourceFunc = getMethod(delegate, @selector(webView:resource:didFinishLoadingFromDataSource:));
1642     cache->didLoadResourceFromMemoryCacheFunc = getMethod(delegate, @selector(webView:didLoadResourceFromMemoryCache:response:length:fromDataSource:));
1643     cache->didReceiveAuthenticationChallengeFunc = getMethod(delegate, @selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:));
1644 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
1645     cache->canAuthenticateAgainstProtectionSpaceFunc = getMethod(delegate, @selector(webView:resource:canAuthenticateAgainstProtectionSpace:forDataSource:));
1646 #endif
1647     cache->didReceiveContentLengthFunc = getMethod(delegate, @selector(webView:resource:didReceiveContentLength:fromDataSource:));
1648     cache->didReceiveResponseFunc = getMethod(delegate, @selector(webView:resource:didReceiveResponse:fromDataSource:));
1649     cache->identifierForRequestFunc = getMethod(delegate, @selector(webView:identifierForInitialRequest:fromDataSource:));
1650     cache->plugInFailedWithErrorFunc = getMethod(delegate, @selector(webView:plugInFailedWithError:dataSource:));
1651     cache->willCacheResponseFunc = getMethod(delegate, @selector(webView:resource:willCacheResponse:fromDataSource:));
1652     cache->willSendRequestFunc = getMethod(delegate, @selector(webView:resource:willSendRequest:redirectResponse:fromDataSource:));
1653     cache->shouldUseCredentialStorageFunc = getMethod(delegate, @selector(webView:resource:shouldUseCredentialStorageForDataSource:));
1654     cache->shouldPaintBrokenImageForURLFunc = getMethod(delegate, @selector(webView:shouldPaintBrokenImageForURL:));
1655 }
1656
1657 - (void)_cacheFrameLoadDelegateImplementations
1658 {
1659     WebFrameLoadDelegateImplementationCache *cache = &_private->frameLoadDelegateImplementations;
1660     id delegate = _private->frameLoadDelegate;
1661
1662     if (!delegate) {
1663         bzero(cache, sizeof(WebFrameLoadDelegateImplementationCache));
1664         return;
1665     }
1666
1667     cache->didCancelClientRedirectForFrameFunc = getMethod(delegate, @selector(webView:didCancelClientRedirectForFrame:));
1668     cache->didChangeLocationWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didChangeLocationWithinPageForFrame:));
1669     cache->didPushStateWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didPushStateWithinPageForFrame:));
1670     cache->didReplaceStateWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didReplaceStateWithinPageForFrame:));
1671     cache->didPopStateWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didPopStateWithinPageForFrame:));
1672 #if JSC_OBJC_API_ENABLED
1673     cache->didCreateJavaScriptContextForFrameFunc = getMethod(delegate, @selector(webView:didCreateJavaScriptContext:forFrame:));
1674 #endif
1675     cache->didClearWindowObjectForFrameFunc = getMethod(delegate, @selector(webView:didClearWindowObject:forFrame:));
1676     cache->didClearWindowObjectForFrameInScriptWorldFunc = getMethod(delegate, @selector(webView:didClearWindowObjectForFrame:inScriptWorld:));
1677     cache->didClearInspectorWindowObjectForFrameFunc = getMethod(delegate, @selector(webView:didClearInspectorWindowObject:forFrame:));
1678     cache->didCommitLoadForFrameFunc = getMethod(delegate, @selector(webView:didCommitLoadForFrame:));
1679     cache->didFailLoadWithErrorForFrameFunc = getMethod(delegate, @selector(webView:didFailLoadWithError:forFrame:));
1680     cache->didFailProvisionalLoadWithErrorForFrameFunc = getMethod(delegate, @selector(webView:didFailProvisionalLoadWithError:forFrame:));
1681     cache->didFinishDocumentLoadForFrameFunc = getMethod(delegate, @selector(webView:didFinishDocumentLoadForFrame:));
1682     cache->didFinishLoadForFrameFunc = getMethod(delegate, @selector(webView:didFinishLoadForFrame:));
1683     cache->didFirstLayoutInFrameFunc = getMethod(delegate, @selector(webView:didFirstLayoutInFrame:));
1684     cache->didFirstVisuallyNonEmptyLayoutInFrameFunc = getMethod(delegate, @selector(webView:didFirstVisuallyNonEmptyLayoutInFrame:));
1685     cache->didLayoutFunc = getMethod(delegate, @selector(webView:didLayout:));
1686     cache->didHandleOnloadEventsForFrameFunc = getMethod(delegate, @selector(webView:didHandleOnloadEventsForFrame:));
1687     cache->didReceiveIconForFrameFunc = getMethod(delegate, @selector(webView:didReceiveIcon:forFrame:));
1688     cache->didReceiveServerRedirectForProvisionalLoadForFrameFunc = getMethod(delegate, @selector(webView:didReceiveServerRedirectForProvisionalLoadForFrame:));
1689     cache->didReceiveTitleForFrameFunc = getMethod(delegate, @selector(webView:didReceiveTitle:forFrame:));
1690     cache->didStartProvisionalLoadForFrameFunc = getMethod(delegate, @selector(webView:didStartProvisionalLoadForFrame:));
1691     cache->willCloseFrameFunc = getMethod(delegate, @selector(webView:willCloseFrame:));
1692     cache->willPerformClientRedirectToURLDelayFireDateForFrameFunc = getMethod(delegate, @selector(webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:));
1693     cache->windowScriptObjectAvailableFunc = getMethod(delegate, @selector(webView:windowScriptObjectAvailable:));
1694     cache->didDisplayInsecureContentFunc = getMethod(delegate, @selector(webViewDidDisplayInsecureContent:));
1695     cache->didRunInsecureContentFunc = getMethod(delegate, @selector(webView:didRunInsecureContent:));
1696     cache->didDetectXSSFunc = getMethod(delegate, @selector(webView:didDetectXSS:));
1697     cache->didRemoveFrameFromHierarchyFunc = getMethod(delegate, @selector(webView:didRemoveFrameFromHierarchy:));
1698
1699     // It would be nice to get rid of this code and transition all clients to using didLayout instead of
1700     // didFirstLayoutInFrame and didFirstVisuallyNonEmptyLayoutInFrame. In the meantime, this is required
1701     // for backwards compatibility.
1702     Page* page = core(self);
1703     if (page) {
1704         unsigned milestones = DidFirstLayout;
1705         if (cache->didFirstVisuallyNonEmptyLayoutInFrameFunc)
1706             milestones |= DidFirstVisuallyNonEmptyLayout;
1707         page->addLayoutMilestones(static_cast<LayoutMilestones>(milestones));
1708     }
1709 }
1710
1711 - (void)_cacheScriptDebugDelegateImplementations
1712 {
1713     WebScriptDebugDelegateImplementationCache *cache = &_private->scriptDebugDelegateImplementations;
1714     id delegate = _private->scriptDebugDelegate;
1715
1716     if (!delegate) {
1717         bzero(cache, sizeof(WebScriptDebugDelegateImplementationCache));
1718         return;
1719     }
1720
1721     cache->didParseSourceFunc = getMethod(delegate, @selector(webView:didParseSource:baseLineNumber:fromURL:sourceId:forWebFrame:));
1722     if (cache->didParseSourceFunc)
1723         cache->didParseSourceExpectsBaseLineNumber = YES;
1724     else {
1725         cache->didParseSourceExpectsBaseLineNumber = NO;
1726         cache->didParseSourceFunc = getMethod(delegate, @selector(webView:didParseSource:fromURL:sourceId:forWebFrame:));
1727     }
1728
1729     cache->failedToParseSourceFunc = getMethod(delegate, @selector(webView:failedToParseSource:baseLineNumber:fromURL:withError:forWebFrame:));
1730
1731     cache->exceptionWasRaisedFunc = getMethod(delegate, @selector(webView:exceptionWasRaised:hasHandler:sourceId:line:forWebFrame:));
1732     if (cache->exceptionWasRaisedFunc)
1733         cache->exceptionWasRaisedExpectsHasHandlerFlag = YES;
1734     else {
1735         cache->exceptionWasRaisedExpectsHasHandlerFlag = NO;
1736         cache->exceptionWasRaisedFunc = getMethod(delegate, @selector(webView:exceptionWasRaised:sourceId:line:forWebFrame:));
1737     }
1738 }
1739
1740 - (void)_cacheHistoryDelegateImplementations
1741 {
1742     WebHistoryDelegateImplementationCache *cache = &_private->historyDelegateImplementations;
1743     id delegate = _private->historyDelegate;
1744
1745     if (!delegate) {
1746         bzero(cache, sizeof(WebHistoryDelegateImplementationCache));
1747         return;
1748     }
1749
1750     cache->navigatedFunc = getMethod(delegate, @selector(webView:didNavigateWithNavigationData:inFrame:));
1751     cache->clientRedirectFunc = getMethod(delegate, @selector(webView:didPerformClientRedirectFromURL:toURL:inFrame:));
1752     cache->serverRedirectFunc = getMethod(delegate, @selector(webView:didPerformServerRedirectFromURL:toURL:inFrame:));
1753     cache->deprecatedSetTitleFunc = getMethod(delegate, @selector(webView:updateHistoryTitle:forURL:));
1754     cache->setTitleFunc = getMethod(delegate, @selector(webView:updateHistoryTitle:forURL:inFrame:));
1755     cache->populateVisitedLinksFunc = getMethod(delegate, @selector(populateVisitedLinksForWebView:));
1756 }
1757
1758 - (id)_policyDelegateForwarder
1759 {
1760     if (!_private->policyDelegateForwarder)
1761         _private->policyDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->policyDelegate defaultTarget:[WebDefaultPolicyDelegate sharedPolicyDelegate]];
1762     return _private->policyDelegateForwarder;
1763 }
1764
1765 - (id)_UIDelegateForwarder
1766 {
1767     if (!_private->UIDelegateForwarder)
1768         _private->UIDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->UIDelegate defaultTarget:[WebDefaultUIDelegate sharedUIDelegate]];
1769     return _private->UIDelegateForwarder;
1770 }
1771
1772 - (id)_editingDelegateForwarder
1773 {
1774     // This can be called during window deallocation by QTMovieView in the QuickTime Cocoa Plug-in.
1775     // Not sure if that is a bug or not.
1776     if (!_private)
1777         return nil;
1778
1779     if (!_private->editingDelegateForwarder)
1780         _private->editingDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->editingDelegate defaultTarget:[WebDefaultEditingDelegate sharedEditingDelegate]];
1781     return _private->editingDelegateForwarder;
1782 }
1783
1784 - (void)_closeWindow
1785 {
1786     [[self _UIDelegateForwarder] webViewClose:self];
1787 }
1788
1789 + (void)_unregisterViewClassAndRepresentationClassForMIMEType:(NSString *)MIMEType
1790 {
1791     [[WebFrameView _viewTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType];
1792     [[WebDataSource _repTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType];
1793     
1794     // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
1795     // in the WebCore MIMEType registry.  For now we're doing this in a safe, limited manner
1796     // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
1797     MIMETypeRegistry::getSupportedNonImageMIMETypes().remove(MIMEType);
1798 }
1799
1800 + (void)_registerViewClass:(Class)viewClass representationClass:(Class)representationClass forURLScheme:(NSString *)URLScheme
1801 {
1802     NSString *MIMEType = [self _generatedMIMETypeForURLScheme:URLScheme];
1803     [self registerViewClass:viewClass representationClass:representationClass forMIMEType:MIMEType];
1804
1805     // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
1806     // in the WebCore MIMEType registry.  For now we're doing this in a safe, limited manner
1807     // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
1808     if ([viewClass class] == [WebHTMLView class])
1809         MIMETypeRegistry::getSupportedNonImageMIMETypes().add(MIMEType);
1810     
1811     // This is used to make _representationExistsForURLScheme faster.
1812     // Without this set, we'd have to create the MIME type each time.
1813     if (schemesWithRepresentationsSet == nil) {
1814         schemesWithRepresentationsSet = [[NSMutableSet alloc] init];
1815     }
1816     [schemesWithRepresentationsSet addObject:[[[URLScheme lowercaseString] copy] autorelease]];
1817 }
1818
1819 + (NSString *)_generatedMIMETypeForURLScheme:(NSString *)URLScheme
1820 {
1821     return [@"x-apple-web-kit/" stringByAppendingString:[URLScheme lowercaseString]];
1822 }
1823
1824 + (BOOL)_representationExistsForURLScheme:(NSString *)URLScheme
1825 {
1826     return [schemesWithRepresentationsSet containsObject:[URLScheme lowercaseString]];
1827 }
1828
1829 + (BOOL)_canHandleRequest:(NSURLRequest *)request forMainFrame:(BOOL)forMainFrame
1830 {
1831     // FIXME: If <rdar://problem/5217309> gets fixed, this check can be removed.
1832     if (!request)
1833         return NO;
1834
1835     if ([NSURLConnection canHandleRequest:request])
1836         return YES;
1837
1838     NSString *scheme = [[request URL] scheme];
1839
1840     // Representations for URL schemes work at the top level.
1841     if (forMainFrame && [self _representationExistsForURLScheme:scheme])
1842         return YES;
1843
1844     if ([scheme _webkit_isCaseInsensitiveEqualToString:@"applewebdata"])
1845         return YES;
1846
1847 #if ENABLE(BLOB)
1848     if ([scheme _webkit_isCaseInsensitiveEqualToString:@"blob"])
1849         return YES;
1850 #endif
1851
1852     return NO;
1853 }
1854
1855 + (BOOL)_canHandleRequest:(NSURLRequest *)request
1856 {
1857     return [self _canHandleRequest:request forMainFrame:YES];
1858 }
1859
1860 + (NSString *)_decodeData:(NSData *)data
1861 {
1862     HTMLNames::init(); // this method is used for importing bookmarks at startup, so HTMLNames are likely to be uninitialized yet
1863     RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("text/html"); // bookmark files are HTML
1864     String result = decoder->decode(static_cast<const char*>([data bytes]), [data length]);
1865     result.append(decoder->flush());
1866     return result;
1867 }
1868
1869 - (void)_pushPerformingProgrammaticFocus
1870 {
1871     _private->programmaticFocusCount++;
1872 }
1873
1874 - (void)_popPerformingProgrammaticFocus
1875 {
1876     _private->programmaticFocusCount--;
1877 }
1878
1879 - (BOOL)_isPerformingProgrammaticFocus
1880 {
1881     return _private->programmaticFocusCount != 0;
1882 }
1883
1884 - (void)_didChangeValueForKey: (NSString *)key
1885 {
1886     LOG (Bindings, "calling didChangeValueForKey: %@", key);
1887     [self didChangeValueForKey: key];
1888 }
1889
1890 - (void)_willChangeValueForKey: (NSString *)key
1891 {
1892     LOG (Bindings, "calling willChangeValueForKey: %@", key);
1893     [self willChangeValueForKey: key];
1894 }
1895
1896 + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key {
1897     static NSSet *manualNotifyKeys = nil;
1898     if (!manualNotifyKeys)
1899         manualNotifyKeys = [[NSSet alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey,
1900             _WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, _WebMainFrameDocumentKey,
1901             nil];
1902     if ([manualNotifyKeys containsObject:key])
1903         return NO;
1904     return YES;
1905 }
1906
1907 - (NSArray *)_declaredKeys {
1908     static NSArray *declaredKeys = nil;
1909     if (!declaredKeys)
1910         declaredKeys = [[NSArray alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey,
1911             _WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, _WebMainFrameDocumentKey, nil];
1912     return declaredKeys;
1913 }
1914
1915 - (void)setObservationInfo:(void *)info
1916 {
1917     _private->observationInfo = info;
1918 }
1919
1920 - (void *)observationInfo
1921 {
1922     return _private->observationInfo;
1923 }
1924
1925 - (void)_willChangeBackForwardKeys
1926 {
1927     [self _willChangeValueForKey: _WebCanGoBackKey];
1928     [self _willChangeValueForKey: _WebCanGoForwardKey];
1929 }
1930
1931 - (void)_didChangeBackForwardKeys
1932 {
1933     [self _didChangeValueForKey: _WebCanGoBackKey];
1934     [self _didChangeValueForKey: _WebCanGoForwardKey];
1935 }
1936
1937 - (void)_didStartProvisionalLoadForFrame:(WebFrame *)frame
1938 {
1939     if (needsSelfRetainWhileLoadingQuirk())
1940         [self retain];
1941
1942     [self _willChangeBackForwardKeys];
1943     if (frame == [self mainFrame]){
1944         // Force an observer update by sending a will/did.
1945         [self _willChangeValueForKey: _WebIsLoadingKey];
1946         [self _didChangeValueForKey: _WebIsLoadingKey];
1947
1948         [self _willChangeValueForKey: _WebMainFrameURLKey];
1949     }
1950
1951     [NSApp setWindowsNeedUpdate:YES];
1952
1953 #if ENABLE(FULLSCREEN_API)
1954     Document* document = core([frame DOMDocument]);
1955     if (Element* element = document ? document->webkitCurrentFullScreenElement() : 0) {
1956         SEL selector = @selector(webView:closeFullScreenWithListener:);
1957         if (_private->UIDelegate && [_private->UIDelegate respondsToSelector:selector]) {
1958             WebKitFullScreenListener *listener = [[WebKitFullScreenListener alloc] initWithElement:element];
1959             CallUIDelegate(self, selector, listener);
1960             [listener release];
1961         } else if (_private->newFullscreenController && [_private->newFullscreenController isFullScreen]) {
1962             [_private->newFullscreenController close];
1963         }
1964     }
1965 #endif
1966 }
1967
1968 - (void)_didCommitLoadForFrame:(WebFrame *)frame
1969 {
1970     if (frame == [self mainFrame])
1971         [self _didChangeValueForKey: _WebMainFrameURLKey];
1972     [NSApp setWindowsNeedUpdate:YES];
1973 }
1974
1975 - (void)_didFinishLoadForFrame:(WebFrame *)frame
1976 {
1977     if (needsSelfRetainWhileLoadingQuirk())
1978         [self performSelector:@selector(release) withObject:nil afterDelay:0];
1979         
1980     [self _didChangeBackForwardKeys];
1981     if (frame == [self mainFrame]){
1982         // Force an observer update by sending a will/did.
1983         [self _willChangeValueForKey: _WebIsLoadingKey];
1984         [self _didChangeValueForKey: _WebIsLoadingKey];
1985     }
1986     [NSApp setWindowsNeedUpdate:YES];
1987 }
1988
1989 - (void)_didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
1990 {
1991     if (needsSelfRetainWhileLoadingQuirk())
1992         [self performSelector:@selector(release) withObject:nil afterDelay:0];
1993
1994     [self _didChangeBackForwardKeys];
1995     if (frame == [self mainFrame]){
1996         // Force an observer update by sending a will/did.
1997         [self _willChangeValueForKey: _WebIsLoadingKey];
1998         [self _didChangeValueForKey: _WebIsLoadingKey];
1999     }
2000     [NSApp setWindowsNeedUpdate:YES];
2001 }
2002
2003 - (void)_didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
2004 {
2005     if (needsSelfRetainWhileLoadingQuirk())
2006         [self performSelector:@selector(release) withObject:nil afterDelay:0];
2007
2008     [self _didChangeBackForwardKeys];
2009     if (frame == [self mainFrame]){
2010         // Force an observer update by sending a will/did.
2011         [self _willChangeValueForKey: _WebIsLoadingKey];
2012         [self _didChangeValueForKey: _WebIsLoadingKey];
2013         
2014         [self _didChangeValueForKey: _WebMainFrameURLKey];
2015     }
2016     [NSApp setWindowsNeedUpdate:YES];
2017 }
2018
2019 - (NSCachedURLResponse *)_cachedResponseForURL:(NSURL *)URL
2020 {
2021     RetainPtr<NSMutableURLRequest *> request = adoptNS([[NSMutableURLRequest alloc] initWithURL:URL]);
2022     [request _web_setHTTPUserAgent:[self userAgentForURL:URL]];
2023     NSCachedURLResponse *cachedResponse;
2024
2025     if (!_private->page)
2026         return nil;
2027
2028     if (CFURLStorageSessionRef storageSession = _private->page->mainFrame().loader().networkingContext()->storageSession().platformSession())
2029         cachedResponse = WKCachedResponseForRequest(storageSession, request.get());
2030     else
2031         cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:request.get()];
2032
2033     return cachedResponse;
2034 }
2035
2036 - (void)_writeImageForElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
2037 {
2038     NSURL *linkURL = [element objectForKey:WebElementLinkURLKey];
2039     DOMElement *domElement = [element objectForKey:WebElementDOMNodeKey];
2040     [pasteboard _web_writeImage:(NSImage *)(domElement ? nil : [element objectForKey:WebElementImageKey])
2041                         element:domElement
2042                             URL:linkURL ? linkURL : (NSURL *)[element objectForKey:WebElementImageURLKey]
2043                           title:[element objectForKey:WebElementImageAltStringKey] 
2044                         archive:[[element objectForKey:WebElementDOMNodeKey] webArchive]
2045                           types:types
2046                          source:nil];
2047 }
2048
2049 - (void)_writeLinkElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
2050 {
2051     [pasteboard _web_writeURL:[element objectForKey:WebElementLinkURLKey]
2052                      andTitle:[element objectForKey:WebElementLinkLabelKey]
2053                         types:types];
2054 }
2055
2056 #if ENABLE(DRAG_SUPPORT)
2057 - (void)_setInitiatedDrag:(BOOL)initiatedDrag
2058 {
2059     if (!_private->page)
2060         return;
2061     _private->page->dragController().setDidInitiateDrag(initiatedDrag);
2062 }
2063 #endif
2064
2065 #if ENABLE(DASHBOARD_SUPPORT)
2066
2067 #define DASHBOARD_CONTROL_LABEL @"control"
2068
2069 - (void)_addControlRect:(NSRect)bounds clip:(NSRect)clip fromView:(NSView *)view toDashboardRegions:(NSMutableDictionary *)regions
2070 {
2071     NSRect adjustedBounds = bounds;
2072     adjustedBounds.origin = [self convertPoint:bounds.origin fromView:view];
2073     adjustedBounds.origin.y = [self bounds].size.height - adjustedBounds.origin.y;
2074     adjustedBounds.size = bounds.size;
2075
2076     NSRect adjustedClip;
2077     adjustedClip.origin = [self convertPoint:clip.origin fromView:view];
2078     adjustedClip.origin.y = [self bounds].size.height - adjustedClip.origin.y;
2079     adjustedClip.size = clip.size;
2080
2081     WebDashboardRegion *region = [[WebDashboardRegion alloc] initWithRect:adjustedBounds 
2082         clip:adjustedClip type:WebDashboardRegionTypeScrollerRectangle];
2083     NSMutableArray *scrollerRegions = [regions objectForKey:DASHBOARD_CONTROL_LABEL];
2084     if (!scrollerRegions) {
2085         scrollerRegions = [[NSMutableArray alloc] init];
2086         [regions setObject:scrollerRegions forKey:DASHBOARD_CONTROL_LABEL];
2087         [scrollerRegions release];
2088     }
2089     [scrollerRegions addObject:region];
2090     [region release];
2091 }
2092
2093 - (void)_addScrollerDashboardRegionsForFrameView:(FrameView*)frameView dashboardRegions:(NSMutableDictionary *)regions
2094 {    
2095     NSView *documentView = [[kit(&frameView->frame()) frameView] documentView];
2096
2097     for (const auto& widget: frameView->children()) {
2098         if (widget->isFrameView()) {
2099             [self _addScrollerDashboardRegionsForFrameView:toFrameView(widget.get()) dashboardRegions:regions];
2100             continue;
2101         }
2102
2103         if (!widget->isScrollbar())
2104             continue;
2105
2106         // FIXME: This should really pass an appropriate clip, but our first try got it wrong, and
2107         // it's not common to need this to be correct in Dashboard widgets.
2108         NSRect bounds = widget->frameRect();
2109         [self _addControlRect:bounds clip:bounds fromView:documentView toDashboardRegions:regions];
2110     }
2111 }
2112
2113 - (void)_addScrollerDashboardRegions:(NSMutableDictionary *)regions from:(NSArray *)views
2114 {
2115     // Add scroller regions for NSScroller and WebCore scrollbars
2116     NSUInteger count = [views count];
2117     for (NSUInteger i = 0; i < count; i++) {
2118         NSView *view = [views objectAtIndex:i];
2119         
2120         if ([view isKindOfClass:[WebHTMLView class]]) {
2121             if (Frame* coreFrame = core([(WebHTMLView*)view _frame])) {
2122                 if (FrameView* coreView = coreFrame->view())
2123                     [self _addScrollerDashboardRegionsForFrameView:coreView dashboardRegions:regions];
2124             }
2125         } else if ([view isKindOfClass:[NSScroller class]]) {
2126             // AppKit places absent scrollers at -100,-100
2127             if ([view frame].origin.y < 0)
2128                 continue;
2129             [self _addControlRect:[view bounds] clip:[view visibleRect] fromView:view toDashboardRegions:regions];
2130         }
2131         [self _addScrollerDashboardRegions:regions from:[view subviews]];
2132     }
2133 }
2134
2135 - (void)_addScrollerDashboardRegions:(NSMutableDictionary *)regions
2136 {
2137     [self _addScrollerDashboardRegions:regions from:[self subviews]];
2138 }
2139
2140 - (NSDictionary *)_dashboardRegions
2141 {
2142     // Only return regions from main frame.
2143     Frame* mainFrame = [self _mainCoreFrame];
2144     if (!mainFrame)
2145         return nil;
2146
2147     const Vector<AnnotatedRegionValue>& regions = mainFrame->document()->annotatedRegions();
2148     size_t size = regions.size();
2149
2150     NSMutableDictionary *webRegions = [NSMutableDictionary dictionaryWithCapacity:size];
2151     for (size_t i = 0; i < size; i++) {
2152         const AnnotatedRegionValue& region = regions[i];
2153
2154         if (region.type == StyleDashboardRegion::None)
2155             continue;
2156
2157         NSString *label = region.label;
2158         WebDashboardRegionType type = WebDashboardRegionTypeNone;
2159         if (region.type == StyleDashboardRegion::Circle)
2160             type = WebDashboardRegionTypeCircle;
2161         else if (region.type == StyleDashboardRegion::Rectangle)
2162             type = WebDashboardRegionTypeRectangle;
2163         NSMutableArray *regionValues = [webRegions objectForKey:label];
2164         if (!regionValues) {
2165             regionValues = [[NSMutableArray alloc] initWithCapacity:1];
2166             [webRegions setObject:regionValues forKey:label];
2167             [regionValues release];
2168         }
2169
2170         WebDashboardRegion *webRegion = [[WebDashboardRegion alloc] initWithRect:pixelSnappedIntRect(region.bounds) clip:pixelSnappedIntRect(region.clip) type:type];
2171         [regionValues addObject:webRegion];
2172         [webRegion release];
2173     }
2174
2175     [self _addScrollerDashboardRegions:webRegions];
2176
2177     return webRegions;
2178 }
2179
2180 - (void)_setDashboardBehavior:(WebDashboardBehavior)behavior to:(BOOL)flag
2181 {
2182     // FIXME: Remove this blanket assignment once Dashboard and Dashcode implement 
2183     // specific support for the backward compatibility mode flag.
2184     if (behavior == WebDashboardBehaviorAllowWheelScrolling && flag == NO && _private->page)
2185         _private->page->settings().setUsesDashboardBackwardCompatibilityMode(true);
2186     
2187     switch (behavior) {
2188         case WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows: {
2189             _private->dashboardBehaviorAlwaysSendMouseEventsToAllWindows = flag;
2190             break;
2191         }
2192         case WebDashboardBehaviorAlwaysSendActiveNullEventsToPlugIns: {
2193             _private->dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns = flag;
2194             break;
2195         }
2196         case WebDashboardBehaviorAlwaysAcceptsFirstMouse: {
2197             _private->dashboardBehaviorAlwaysAcceptsFirstMouse = flag;
2198             break;
2199         }
2200         case WebDashboardBehaviorAllowWheelScrolling: {
2201             _private->dashboardBehaviorAllowWheelScrolling = flag;
2202             break;
2203         }
2204         case WebDashboardBehaviorUseBackwardCompatibilityMode: {
2205             if (_private->page)
2206                 _private->page->settings().setUsesDashboardBackwardCompatibilityMode(flag);
2207 #if ENABLE(LEGACY_CSS_VENDOR_PREFIXES)
2208             RuntimeEnabledFeatures::sharedFeatures().setLegacyCSSVendorPrefixesEnabled(flag);
2209 #endif
2210             break;
2211         }
2212     }
2213
2214     // Pre-HTML5 parser quirks should be enabled if Dashboard is in backward
2215     // compatibility mode. See <rdar://problem/8175982>.
2216     if (_private->page)
2217         _private->page->settings().setUsePreHTML5ParserQuirks([self _needsPreHTML5ParserQuirks]);
2218 }
2219
2220 - (BOOL)_dashboardBehavior:(WebDashboardBehavior)behavior
2221 {
2222     switch (behavior) {
2223         case WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows: {
2224             return _private->dashboardBehaviorAlwaysSendMouseEventsToAllWindows;
2225         }
2226         case WebDashboardBehaviorAlwaysSendActiveNullEventsToPlugIns: {
2227             return _private->dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns;
2228         }
2229         case WebDashboardBehaviorAlwaysAcceptsFirstMouse: {
2230             return _private->dashboardBehaviorAlwaysAcceptsFirstMouse;
2231         }
2232         case WebDashboardBehaviorAllowWheelScrolling: {
2233             return _private->dashboardBehaviorAllowWheelScrolling;
2234         }
2235         case WebDashboardBehaviorUseBackwardCompatibilityMode: {
2236             return _private->page && _private->page->settings().usesDashboardBackwardCompatibilityMode();
2237         }
2238     }
2239     return NO;
2240 }
2241
2242 #endif /* ENABLE(DASHBOARD_SUPPORT) */
2243
2244 + (void)_setShouldUseFontSmoothing:(BOOL)f
2245 {
2246     Font::setShouldUseSmoothing(f);
2247 }
2248
2249 + (BOOL)_shouldUseFontSmoothing
2250 {
2251     return Font::shouldUseSmoothing();
2252 }
2253
2254 + (void)_setUsesTestModeFocusRingColor:(BOOL)f
2255 {
2256     setUsesTestModeFocusRingColor(f);
2257 }
2258
2259 + (BOOL)_usesTestModeFocusRingColor
2260 {
2261     return usesTestModeFocusRingColor();
2262 }
2263
2264 - (void)setAlwaysShowVerticalScroller:(BOOL)flag
2265 {
2266     WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
2267     if (flag) {
2268         [scrollview setVerticalScrollingMode:ScrollbarAlwaysOn andLock:YES];
2269     } else {
2270         [scrollview setVerticalScrollingModeLocked:NO];
2271         [scrollview setVerticalScrollingMode:ScrollbarAuto andLock:NO];
2272     }
2273 }
2274
2275 - (BOOL)alwaysShowVerticalScroller
2276 {
2277     WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
2278     return [scrollview verticalScrollingModeLocked] && [scrollview verticalScrollingMode] == ScrollbarAlwaysOn;
2279 }
2280
2281 - (void)setAlwaysShowHorizontalScroller:(BOOL)flag
2282 {
2283     WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
2284     if (flag) {
2285         [scrollview setHorizontalScrollingMode:ScrollbarAlwaysOn andLock:YES];
2286     } else {
2287         [scrollview setHorizontalScrollingModeLocked:NO];
2288         [scrollview setHorizontalScrollingMode:ScrollbarAuto andLock:NO];
2289     }
2290 }
2291
2292 - (void)setProhibitsMainFrameScrolling:(BOOL)prohibits
2293 {
2294     if (Frame* mainFrame = [self _mainCoreFrame])
2295         mainFrame->view()->setProhibitsScrolling(prohibits);
2296 }
2297
2298 - (BOOL)alwaysShowHorizontalScroller
2299 {
2300     WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
2301     return [scrollview horizontalScrollingModeLocked] && [scrollview horizontalScrollingMode] == ScrollbarAlwaysOn;
2302 }
2303
2304 - (void)_setInViewSourceMode:(BOOL)flag
2305 {
2306     if (Frame* mainFrame = [self _mainCoreFrame])
2307         mainFrame->setInViewSourceMode(flag);
2308 }
2309
2310 - (BOOL)_inViewSourceMode
2311 {
2312     Frame* mainFrame = [self _mainCoreFrame];
2313     return mainFrame && mainFrame->inViewSourceMode();
2314 }
2315
2316 - (void)_setUseFastImageScalingMode:(BOOL)flag
2317 {
2318     if (_private->page && _private->page->inLowQualityImageInterpolationMode() != flag) {
2319         _private->page->setInLowQualityImageInterpolationMode(flag);
2320         [self setNeedsDisplay:YES];
2321     }
2322 }
2323
2324 - (BOOL)_inFastImageScalingMode
2325 {
2326     if (_private->page)
2327         return _private->page->inLowQualityImageInterpolationMode();
2328     return NO;
2329 }
2330
2331 - (BOOL)_cookieEnabled
2332 {
2333     if (_private->page)
2334         return _private->page->settings().cookieEnabled();
2335     return YES;
2336 }
2337
2338 - (void)_setCookieEnabled:(BOOL)enable
2339 {
2340     if (_private->page)
2341         _private->page->settings().setCookieEnabled(enable);
2342 }
2343
2344 - (void)_setAdditionalWebPlugInPaths:(NSArray *)newPaths
2345 {
2346     if (!_private->pluginDatabase)
2347         _private->pluginDatabase = [[WebPluginDatabase alloc] init];
2348         
2349     [_private->pluginDatabase setPlugInPaths:newPaths];
2350     [_private->pluginDatabase refresh];
2351 }
2352
2353 - (void)_attachScriptDebuggerToAllFrames
2354 {
2355     for (Frame* frame = [self _mainCoreFrame]; frame; frame = frame->tree().traverseNext())
2356         [kit(frame) _attachScriptDebugger];
2357 }
2358
2359 - (void)_detachScriptDebuggerFromAllFrames
2360 {
2361     for (Frame* frame = [self _mainCoreFrame]; frame; frame = frame->tree().traverseNext())
2362         [kit(frame) _detachScriptDebugger];
2363 }
2364
2365 - (void)setBackgroundColor:(NSColor *)backgroundColor
2366 {
2367     if ([_private->backgroundColor isEqual:backgroundColor])
2368         return;
2369
2370     id old = _private->backgroundColor;
2371     _private->backgroundColor = [backgroundColor retain];
2372     [old release];
2373
2374     [[self mainFrame] _updateBackgroundAndUpdatesWhileOffscreen];
2375 }
2376
2377 - (NSColor *)backgroundColor
2378 {
2379     return _private->backgroundColor;
2380 }
2381
2382 - (BOOL)defersCallbacks
2383 {
2384     if (!_private->page)
2385         return NO;
2386     return _private->page->defersLoading();
2387 }
2388
2389 - (void)setDefersCallbacks:(BOOL)defer
2390 {
2391     if (!_private->page)
2392         return;
2393     return _private->page->setDefersLoading(defer);
2394 }
2395
2396 // For backwards compatibility with the WebBackForwardList API, we honor both
2397 // a per-WebView and a per-preferences setting for whether to use the page cache.
2398
2399 - (BOOL)usesPageCache
2400 {
2401     return _private->usesPageCache && [[self preferences] usesPageCache];
2402 }
2403
2404 - (void)setUsesPageCache:(BOOL)usesPageCache
2405 {
2406     _private->usesPageCache = usesPageCache;
2407
2408     // Update our own settings and post the public notification only
2409     [self _preferencesChanged:[self preferences]];
2410     [[self preferences] _postPreferencesChangedAPINotification];
2411 }
2412
2413 - (WebHistoryItem *)_globalHistoryItem
2414 {
2415     if (!_private)
2416         return nil;
2417
2418     return kit(_private->_globalHistoryItem.get());
2419 }
2420
2421 - (void)_setGlobalHistoryItem:(HistoryItem*)historyItem
2422 {
2423     _private->_globalHistoryItem = historyItem;
2424 }
2425
2426 - (WebTextIterator *)textIteratorForRect:(NSRect)rect
2427 {
2428     IntPoint rectStart(rect.origin.x, rect.origin.y);
2429     IntPoint rectEnd(rect.origin.x + rect.size.width, rect.origin.y + rect.size.height);
2430     
2431     Frame* coreFrame = [self _mainCoreFrame];
2432     if (!coreFrame)
2433         return nil;
2434     
2435     VisibleSelection selectionInsideRect(coreFrame->visiblePositionForPoint(rectStart), coreFrame->visiblePositionForPoint(rectEnd));
2436     
2437     return [[[WebTextIterator alloc] initWithRange:kit(selectionInsideRect.toNormalizedRange().get())] autorelease];
2438 }
2439
2440 - (void)handleAuthenticationForResource:(id)identifier challenge:(NSURLAuthenticationChallenge *)challenge fromDataSource:(WebDataSource *)dataSource 
2441 {
2442     NSWindow *window = [self hostWindow] ? [self hostWindow] : [self window]; 
2443     [[WebPanelAuthenticationHandler sharedHandler] startAuthentication:challenge window:window]; 
2444
2445
2446 - (void)_clearUndoRedoOperations
2447 {
2448     if (!_private->page)
2449         return;
2450     _private->page->clearUndoRedoOperations();
2451 }
2452
2453 - (void)_executeCoreCommandByName:(NSString *)name value:(NSString *)value
2454 {
2455     Frame* coreFrame = [self _mainCoreFrame];
2456     if (!coreFrame)
2457         return;
2458     coreFrame->editor().command(name).execute(value);
2459 }
2460
2461 - (void)_setCustomHTMLTokenizerTimeDelay:(double)timeDelay
2462 {
2463     if (!_private->page)
2464         return;
2465     return _private->page->setCustomHTMLTokenizerTimeDelay(timeDelay);
2466 }
2467
2468 - (void)_setCustomHTMLTokenizerChunkSize:(int)chunkSize
2469 {
2470     if (!_private->page)
2471         return;
2472     return _private->page->setCustomHTMLTokenizerChunkSize(chunkSize);
2473 }
2474
2475 - (void)_clearMainFrameName
2476 {
2477     _private->page->mainFrame().tree().clearName();
2478 }
2479
2480 - (void)setSelectTrailingWhitespaceEnabled:(BOOL)flag
2481 {
2482     if (_private->page->settings().selectTrailingWhitespaceEnabled() != flag) {
2483         _private->page->settings().setSelectTrailingWhitespaceEnabled(flag);
2484         [self setSmartInsertDeleteEnabled:!flag];
2485     }
2486 }
2487
2488 - (BOOL)isSelectTrailingWhitespaceEnabled
2489 {
2490     return _private->page->settings().selectTrailingWhitespaceEnabled();
2491 }
2492
2493 - (void)setMemoryCacheDelegateCallsEnabled:(BOOL)enabled
2494 {
2495     _private->page->setMemoryCacheClientCallsEnabled(enabled);
2496 }
2497
2498 - (BOOL)areMemoryCacheDelegateCallsEnabled
2499 {
2500     return _private->page->areMemoryCacheClientCallsEnabled();
2501 }
2502
2503 + (NSCursor *)_pointingHandCursor
2504 {
2505     return handCursor().platformCursor();
2506 }
2507
2508 - (BOOL)_postsAcceleratedCompositingNotifications
2509 {
2510 #if USE(ACCELERATED_COMPOSITING)
2511     return _private->postsAcceleratedCompositingNotifications;
2512 #else
2513     return NO;
2514 #endif
2515
2516 }
2517 - (void)_setPostsAcceleratedCompositingNotifications:(BOOL)flag
2518 {
2519 #if USE(ACCELERATED_COMPOSITING)
2520     _private->postsAcceleratedCompositingNotifications = flag;
2521 #endif
2522 }
2523
2524 - (BOOL)_isUsingAcceleratedCompositing
2525 {
2526 #if USE(ACCELERATED_COMPOSITING)
2527     Frame* coreFrame = [self _mainCoreFrame];
2528     for (Frame* frame = coreFrame; frame; frame = frame->tree().traverseNext(coreFrame)) {
2529         NSView *documentView = [[kit(frame) frameView] documentView];
2530         if ([documentView isKindOfClass:[WebHTMLView class]] && [(WebHTMLView *)documentView _isUsingAcceleratedCompositing])
2531             return YES;
2532     }
2533 #endif
2534     return NO;
2535 }
2536
2537 - (void)_setBaseCTM:(CGAffineTransform)transform forContext:(CGContextRef)context
2538 {
2539     WKSetBaseCTM(context, transform);
2540 }
2541
2542 - (BOOL)interactiveFormValidationEnabled
2543 {
2544     return _private->interactiveFormValidationEnabled;
2545 }
2546
2547 - (void)setInteractiveFormValidationEnabled:(BOOL)enabled
2548 {
2549     _private->interactiveFormValidationEnabled = enabled;
2550 }
2551
2552 - (int)validationMessageTimerMagnification
2553 {
2554     return _private->validationMessageTimerMagnification;
2555 }
2556
2557 - (void)setValidationMessageTimerMagnification:(int)newValue
2558 {
2559     _private->validationMessageTimerMagnification = newValue;
2560 }
2561
2562 - (BOOL)_isSoftwareRenderable
2563 {
2564 #if USE(ACCELERATED_COMPOSITING)
2565     Frame* coreFrame = [self _mainCoreFrame];
2566     for (Frame* frame = coreFrame; frame; frame = frame->tree().traverseNext(coreFrame)) {
2567         if (FrameView* view = frame->view()) {
2568             if (!view->isSoftwareRenderable())
2569                 return NO;
2570         }
2571     }
2572 #endif
2573     return YES;
2574 }
2575
2576 - (void)_setIncludesFlattenedCompositingLayersWhenDrawingToBitmap:(BOOL)flag
2577 {
2578     _private->includesFlattenedCompositingLayersWhenDrawingToBitmap = flag;
2579 }
2580
2581 - (BOOL)_includesFlattenedCompositingLayersWhenDrawingToBitmap
2582 {
2583     return _private->includesFlattenedCompositingLayersWhenDrawingToBitmap;
2584 }
2585
2586 - (void)setTracksRepaints:(BOOL)flag
2587 {
2588     Frame* coreFrame = [self _mainCoreFrame];
2589     if (FrameView* view = coreFrame->view())
2590         view->setTracksRepaints(flag);
2591 }
2592
2593 - (BOOL)isTrackingRepaints
2594 {
2595     Frame* coreFrame = [self _mainCoreFrame];
2596     if (FrameView* view = coreFrame->view())
2597         return view->isTrackingRepaints();
2598     
2599     return NO;
2600 }
2601
2602 - (void)resetTrackedRepaints
2603 {
2604     Frame* coreFrame = [self _mainCoreFrame];
2605     if (FrameView* view = coreFrame->view())
2606         view->resetTrackedRepaints();
2607 }
2608
2609 - (NSArray*)trackedRepaintRects
2610 {
2611     Frame* coreFrame = [self _mainCoreFrame];
2612     FrameView* view = coreFrame->view();
2613     if (!view || !view->isTrackingRepaints())
2614         return nil;
2615
2616     const Vector<IntRect>& repaintRects = view->trackedRepaintRects();
2617     NSMutableArray* rectsArray = [[NSMutableArray alloc] initWithCapacity:repaintRects.size()];
2618     
2619     for (unsigned i = 0; i < repaintRects.size(); ++i)
2620         [rectsArray addObject:[NSValue valueWithRect:pixelSnappedIntRect(repaintRects[i])]];
2621
2622     return [rectsArray autorelease];
2623 }
2624
2625 - (NSPasteboard *)_insertionPasteboard
2626 {
2627     return _private ? _private->insertionPasteboard : nil;
2628 }
2629
2630 + (void)_addOriginAccessWhitelistEntryWithSourceOrigin:(NSString *)sourceOrigin destinationProtocol:(NSString *)destinationProtocol destinationHost:(NSString *)destinationHost allowDestinationSubdomains:(BOOL)allowDestinationSubdomains
2631 {
2632     SecurityPolicy::addOriginAccessWhitelistEntry(*SecurityOrigin::createFromString(sourceOrigin), destinationProtocol, destinationHost, allowDestinationSubdomains);
2633 }
2634
2635 + (void)_removeOriginAccessWhitelistEntryWithSourceOrigin:(NSString *)sourceOrigin destinationProtocol:(NSString *)destinationProtocol destinationHost:(NSString *)destinationHost allowDestinationSubdomains:(BOOL)allowDestinationSubdomains
2636 {
2637     SecurityPolicy::removeOriginAccessWhitelistEntry(*SecurityOrigin::createFromString(sourceOrigin), destinationProtocol, destinationHost, allowDestinationSubdomains);
2638 }
2639
2640 + (void)_resetOriginAccessWhitelists
2641 {
2642     SecurityPolicy::resetOriginAccessWhitelists();
2643 }
2644
2645 - (BOOL)_isViewVisible
2646 {
2647     if (![self window])
2648         return false;
2649
2650     if (![[self window] isVisible])
2651         return false;
2652
2653     if ([self isHiddenOrHasHiddenAncestor])
2654         return false;
2655
2656     return true;
2657 }
2658
2659 - (void)_updateVisibilityState
2660 {
2661     if (_private && _private->page)
2662         [self _setVisibilityState:([self _isViewVisible] ? WebPageVisibilityStateVisible : WebPageVisibilityStateHidden) isInitialState:NO];
2663 }
2664
2665 - (void)_updateActiveState
2666 {
2667     if (_private && _private->page)
2668         _private->page->focusController().setActive([[self window] _hasKeyAppearance]);
2669 }
2670
2671 static Vector<String> toStringVector(NSArray* patterns)
2672 {
2673     Vector<String> patternsVector;
2674
2675     NSUInteger count = [patterns count];
2676     if (!count)
2677         return patternsVector;
2678
2679     for (NSUInteger i = 0; i < count; ++i) {
2680         id entry = [patterns objectAtIndex:i];
2681         if ([entry isKindOfClass:[NSString class]])
2682             patternsVector.append(String((NSString *)entry));
2683     }
2684     return patternsVector;
2685 }
2686
2687 + (void)_addUserScriptToGroup:(NSString *)groupName world:(WebScriptWorld *)world source:(NSString *)source url:(NSURL *)url
2688                     whitelist:(NSArray *)whitelist blacklist:(NSArray *)blacklist
2689                 injectionTime:(WebUserScriptInjectionTime)injectionTime
2690 {
2691     [WebView _addUserScriptToGroup:groupName world:world source:source url:url whitelist:whitelist blacklist:blacklist injectionTime:injectionTime injectedFrames:WebInjectInAllFrames];
2692 }
2693
2694 + (void)_addUserScriptToGroup:(NSString *)groupName world:(WebScriptWorld *)world source:(NSString *)source url:(NSURL *)url
2695                     whitelist:(NSArray *)whitelist blacklist:(NSArray *)blacklist
2696                 injectionTime:(WebUserScriptInjectionTime)injectionTime
2697                injectedFrames:(WebUserContentInjectedFrames)injectedFrames
2698 {
2699     String group(groupName);
2700     if (group.isEmpty())
2701         return;
2702     
2703     PageGroup* pageGroup = PageGroup::pageGroup(group);
2704     if (!pageGroup)
2705         return;
2706
2707     if (!world)
2708         return;
2709
2710     pageGroup->addUserScriptToWorld(*core(world), source, url, toStringVector(whitelist), toStringVector(blacklist),
2711                                     injectionTime == WebInjectAtDocumentStart ? InjectAtDocumentStart : InjectAtDocumentEnd,
2712                                     injectedFrames == WebInjectInAllFrames ? InjectInAllFrames : InjectInTopFrameOnly);
2713 }
2714
2715 + (void)_addUserStyleSheetToGroup:(NSString *)groupName world:(WebScriptWorld *)world source:(NSString *)source url:(NSURL *)url
2716                         whitelist:(NSArray *)whitelist blacklist:(NSArray *)blacklist
2717 {
2718     [WebView _addUserStyleSheetToGroup:groupName world:world source:source url:url whitelist:whitelist blacklist:blacklist injectedFrames:WebInjectInAllFrames];
2719 }
2720
2721 + (void)_addUserStyleSheetToGroup:(NSString *)groupName world:(WebScriptWorld *)world source:(NSString *)source url:(NSURL *)url
2722                         whitelist:(NSArray *)whitelist blacklist:(NSArray *)blacklist
2723                    injectedFrames:(WebUserContentInjectedFrames)injectedFrames
2724 {
2725     String group(groupName);
2726     if (group.isEmpty())
2727         return;
2728     
2729     PageGroup* pageGroup = PageGroup::pageGroup(group);
2730     if (!pageGroup)
2731         return;
2732
2733     if (!world)
2734         return;
2735
2736     pageGroup->addUserStyleSheetToWorld(*core(world), source, url, toStringVector(whitelist), toStringVector(blacklist), injectedFrames == WebInjectInAllFrames ? InjectInAllFrames : InjectInTopFrameOnly);
2737 }
2738
2739 + (void)_removeUserScriptFromGroup:(NSString *)groupName world:(WebScriptWorld *)world url:(NSURL *)url
2740 {
2741     String group(groupName);
2742     if (group.isEmpty())
2743         return;
2744     
2745     PageGroup* pageGroup = PageGroup::pageGroup(group);
2746     if (!pageGroup)
2747         return;
2748
2749     if (!world)
2750         return;
2751
2752     pageGroup->removeUserScriptFromWorld(*core(world), url);
2753 }
2754
2755 + (void)_removeUserStyleSheetFromGroup:(NSString *)groupName world:(WebScriptWorld *)world url:(NSURL *)url
2756 {
2757     String group(groupName);
2758     if (group.isEmpty())
2759         return;
2760     
2761     PageGroup* pageGroup = PageGroup::pageGroup(group);
2762     if (!pageGroup)
2763         return;
2764
2765     if (!world)
2766         return;
2767
2768     pageGroup->removeUserStyleSheetFromWorld(*core(world), url);
2769 }
2770
2771 + (void)_removeUserScriptsFromGroup:(NSString *)groupName world:(WebScriptWorld *)world
2772 {
2773     String group(groupName);
2774     if (group.isEmpty())
2775         return;
2776     
2777     PageGroup* pageGroup = PageGroup::pageGroup(group);
2778     if (!pageGroup)
2779         return;
2780
2781     if (!world)
2782         return;
2783
2784     pageGroup->removeUserScriptsFromWorld(*core(world));
2785 }
2786
2787 + (void)_removeUserStyleSheetsFromGroup:(NSString *)groupName world:(WebScriptWorld *)world
2788 {
2789     String group(groupName);
2790     if (group.isEmpty())
2791         return;
2792     
2793     PageGroup* pageGroup = PageGroup::pageGroup(group);
2794     if (!pageGroup)
2795         return;
2796
2797     if (!world)
2798         return;
2799
2800     pageGroup->removeUserStyleSheetsFromWorld(*core(world));
2801 }
2802
2803 + (void)_removeAllUserContentFromGroup:(NSString *)groupName
2804 {
2805     String group(groupName);
2806     if (group.isEmpty())
2807         return;
2808     
2809     PageGroup* pageGroup = PageGroup::pageGroup(group);
2810     if (!pageGroup)
2811         return;
2812     
2813     pageGroup->removeAllUserContent();
2814 }
2815
2816 - (BOOL)allowsNewCSSAnimationsWhileSuspended
2817 {
2818     Frame* frame = core([self mainFrame]);
2819     if (frame)
2820         return frame->animation().allowsNewAnimationsWhileSuspended();
2821
2822     return false;
2823 }
2824
2825 - (void)setAllowsNewCSSAnimationsWhileSuspended:(BOOL)allowed
2826 {
2827     Frame* frame = core([self mainFrame]);
2828     if (frame)
2829         frame->animation().setAllowsNewAnimationsWhileSuspended(allowed);
2830 }
2831
2832 - (BOOL)cssAnimationsSuspended
2833 {
2834     // should ask the page!
2835     Frame* frame = core([self mainFrame]);
2836     if (frame)
2837         return frame->animation().isSuspended();
2838
2839     return false;
2840 }
2841
2842 - (void)setCSSAnimationsSuspended:(BOOL)suspended
2843 {
2844     Frame* frame = core([self mainFrame]);
2845     if (suspended == frame->animation().isSuspended())
2846         return;
2847         
2848     if (suspended)
2849         frame->animation().suspendAnimations();
2850     else
2851         frame->animation().resumeAnimations();
2852 }
2853
2854 + (void)_setDomainRelaxationForbidden:(BOOL)forbidden forURLScheme:(NSString *)scheme
2855 {
2856     SchemeRegistry::setDomainRelaxationForbiddenForURLScheme(forbidden, scheme);
2857 }
2858
2859 + (void)_registerURLSchemeAsSecure:(NSString *)scheme
2860 {
2861     SchemeRegistry::registerURLSchemeAsSecure(scheme);
2862 }
2863
2864 + (void)_registerURLSchemeAsAllowingLocalStorageAccessInPrivateBrowsing:(NSString *)scheme
2865 {
2866     SchemeRegistry::registerURLSchemeAsAllowingLocalStorageAccessInPrivateBrowsing(scheme);
2867 }
2868
2869 + (void)_registerURLSchemeAsAllowingDatabaseAccessInPrivateBrowsing:(NSString *)scheme
2870 {
2871     SchemeRegistry::registerURLSchemeAsAllowingDatabaseAccessInPrivateBrowsing(scheme);
2872 }
2873
2874 - (void)_scaleWebView:(float)scale atOrigin:(NSPoint)origin
2875 {
2876     _private->page->setPageScaleFactor(scale, IntPoint(origin));
2877 }
2878
2879 - (float)_viewScaleFactor
2880 {
2881     return _private->page->pageScaleFactor();
2882 }
2883
2884 - (void)_setUseFixedLayout:(BOOL)fixed
2885 {
2886     Frame* coreFrame = [self _mainCoreFrame];
2887     if (!coreFrame)
2888         return;
2889
2890     FrameView* view = coreFrame->view();
2891     if (!view)
2892         return;
2893
2894     view->setUseFixedLayout(fixed);
2895     if (!fixed)
2896         view->setFixedLayoutSize(IntSize());
2897 }
2898
2899 - (void)_setFixedLayoutSize:(NSSize)size
2900 {
2901     Frame* coreFrame = [self _mainCoreFrame];
2902     if (!coreFrame)
2903         return;
2904     
2905     FrameView* view = coreFrame->view();
2906     if (!view)
2907         return;
2908     
2909     view->setFixedLayoutSize(IntSize(size));
2910     view->forceLayout();
2911 }
2912
2913 - (BOOL)_useFixedLayout
2914 {
2915     Frame* coreFrame = [self _mainCoreFrame];
2916     if (!coreFrame)
2917         return NO;
2918     
2919     FrameView* view = coreFrame->view();
2920     if (!view)
2921         return NO;
2922     
2923     return view->useFixedLayout();
2924 }
2925
2926 - (NSSize)_fixedLayoutSize
2927 {
2928     Frame* coreFrame = [self _mainCoreFrame];
2929     if (!coreFrame)
2930         return IntSize();
2931     
2932     FrameView* view = coreFrame->view();
2933     if (!view)
2934         return IntSize();
2935
2936     return view->fixedLayoutSize();
2937 }
2938
2939 - (void)_setPaginationMode:(WebPaginationMode)paginationMode
2940 {
2941     Page* page = core(self);
2942     if (!page)
2943         return;
2944
2945     Pagination pagination = page->pagination();
2946     switch (paginationMode) {
2947     case WebPaginationModeUnpaginated:
2948         pagination.mode = Pagination::Unpaginated;
2949         break;
2950     case WebPaginationModeLeftToRight:
2951         pagination.mode = Pagination::LeftToRightPaginated;
2952         break;
2953     case WebPaginationModeRightToLeft:
2954         pagination.mode = Pagination::RightToLeftPaginated;
2955         break;
2956     case WebPaginationModeTopToBottom:
2957         pagination.mode = Pagination::TopToBottomPaginated;
2958         break;
2959     case WebPaginationModeBottomToTop:
2960         pagination.mode = Pagination::BottomToTopPaginated;
2961         break;
2962     default:
2963         return;
2964     }
2965
2966     page->setPagination(pagination);
2967 }
2968
2969 - (WebPaginationMode)_paginationMode
2970 {
2971     Page* page = core(self);
2972     if (!page)
2973         return WebPaginationModeUnpaginated;
2974
2975     switch (page->pagination().mode) {
2976     case Pagination::Unpaginated:
2977         return WebPaginationModeUnpaginated;
2978     case Pagination::LeftToRightPaginated:
2979         return WebPaginationModeLeftToRight;
2980     case Pagination::RightToLeftPaginated:
2981         return WebPaginationModeRightToLeft;
2982     case Pagination::TopToBottomPaginated:
2983         return WebPaginationModeTopToBottom;
2984     case Pagination::BottomToTopPaginated:
2985         return WebPaginationModeBottomToTop;
2986     }
2987
2988     ASSERT_NOT_REACHED();
2989     return WebPaginationModeUnpaginated;
2990 }
2991
2992 - (void)_listenForLayoutMilestones:(WebLayoutMilestones)layoutMilestones
2993 {
2994     Page* page = core(self);
2995     if (!page)
2996         return;
2997
2998     page->addLayoutMilestones(coreLayoutMilestones(layoutMilestones));
2999 }
3000
3001 - (WebLayoutMilestones)_layoutMilestones
3002 {
3003     Page* page = core(self);
3004     if (!page)
3005         return 0;
3006
3007     return kitLayoutMilestones(page->requestedLayoutMilestones());
3008 }
3009
3010 - (WebPageVisibilityState)_visibilityState
3011 {
3012 #if ENABLE(PAGE_VISIBILITY_API) || ENABLE(HIDDEN_PAGE_DOM_TIMER_THROTTLING)
3013     if (_private->page)
3014         return kit(_private->page->visibilityState());
3015 #endif
3016     return WebPageVisibilityStateVisible;
3017 }
3018
3019 - (void)_setVisibilityState:(WebPageVisibilityState)visibilityState isInitialState:(BOOL)isInitialState
3020 {
3021 #if ENABLE(PAGE_VISIBILITY_API) || ENABLE(HIDDEN_PAGE_DOM_TIMER_THROTTLING)
3022     if (_private->page)
3023         _private->page->setVisibilityState(core(visibilityState), isInitialState);
3024 #endif
3025 }
3026
3027 - (void)_setPaginationBehavesLikeColumns:(BOOL)behavesLikeColumns
3028 {
3029     Page* page = core(self);
3030     if (!page)
3031         return;
3032
3033     Pagination pagination = page->pagination();
3034     pagination.behavesLikeColumns = behavesLikeColumns;
3035
3036     page->setPagination(pagination);
3037 }
3038
3039 - (BOOL)_paginationBehavesLikeColumns
3040 {
3041     Page* page = core(self);
3042     if (!page)
3043         return NO;
3044
3045     return page->pagination().behavesLikeColumns;
3046 }
3047
3048 - (void)_setPageLength:(CGFloat)pageLength
3049 {
3050     Page* page = core(self);
3051     if (!page)
3052         return;
3053
3054     Pagination pagination = page->pagination();
3055     pagination.pageLength = pageLength;
3056
3057     page->setPagination(pagination);
3058 }
3059
3060 - (CGFloat)_pageLength
3061 {
3062     Page* page = core(self);
3063     if (!page)
3064         return 1;
3065
3066     return page->pagination().pageLength;
3067 }
3068
3069 - (void)_setGapBetweenPages:(CGFloat)pageGap
3070 {
3071     Page* page = core(self);
3072     if (!page)
3073         return;
3074
3075     Pagination pagination = page->pagination();
3076     pagination.gap = pageGap;
3077     page->setPagination(pagination);
3078 }
3079
3080 - (CGFloat)_gapBetweenPages
3081 {
3082     Page* page = core(self);
3083     if (!page)
3084         return 0;
3085
3086     return page->pagination().gap;
3087 }
3088
3089 - (NSUInteger)_pageCount
3090 {
3091     Page* page = core(self);
3092     if (!page)
3093         return 0;
3094
3095     return page->pageCount();
3096 }
3097
3098 - (CGFloat)_backingScaleFactor
3099 {
3100     return [self _deviceScaleFactor];
3101 }
3102
3103 - (void)_setCustomBackingScaleFactor:(CGFloat)customScaleFactor
3104 {
3105     float oldScaleFactor = [self _deviceScaleFactor];
3106
3107     _private->customDeviceScaleFactor = customScaleFactor;
3108
3109     if (oldScaleFactor != [self _deviceScaleFactor])
3110         _private->page->setDeviceScaleFactor([self _deviceScaleFactor]);
3111 }
3112
3113 - (NSUInteger)markAllMatchesForText:(NSString *)string caseSensitive:(BOOL)caseFlag highlight:(BOOL)highlight limit:(NSUInteger)limit
3114 {
3115     return [self countMatchesForText:string options:(caseFlag ? 0 : WebFindOptionsCaseInsensitive) highlight:highlight limit:limit markMatches:YES];
3116 }
3117
3118 - (NSUInteger)countMatchesForText:(NSString *)string caseSensitive:(BOOL)caseFlag highlight:(BOOL)highlight limit:(NSUInteger)limit markMatches:(BOOL)markMatches
3119 {
3120     return [self countMatchesForText:string options:(caseFlag ? 0 : WebFindOptionsCaseInsensitive) highlight:highlight limit:limit markMatches:markMatches];
3121 }
3122
3123 - (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag startInSelection:(BOOL)startInSelection
3124 {
3125     return [self findString:string options:((forward ? 0 : WebFindOptionsBackwards) | (caseFlag ? 0 : WebFindOptionsCaseInsensitive) | (wrapFlag ? WebFindOptionsWrapAround : 0) | (startInSelection ? WebFindOptionsStartInSelection : 0))];
3126 }
3127
3128 + (void)_setLoadResourcesSerially:(BOOL)serialize 
3129 {
3130     WebPlatformStrategies::initializeIfNecessary();
3131     resourceLoadScheduler()->setSerialLoadingEnabled(serialize);
3132 }
3133
3134 + (BOOL)_HTTPPipeliningEnabled
3135 {
3136     return ResourceRequest::httpPipeliningEnabled();
3137 }
3138
3139 + (void)_setHTTPPipeliningEnabled:(BOOL)enabled
3140 {
3141     ResourceRequest::setHTTPPipeliningEnabled(enabled);
3142 }
3143
3144 - (void)_setSourceApplicationAuditData:(NSData *)sourceApplicationAuditData
3145 {
3146     if (_private->sourceApplicationAuditData == sourceApplicationAuditData)
3147         return;
3148
3149     _private->sourceApplicationAuditData = adoptNS([sourceApplicationAuditData copy]);
3150 }
3151
3152 - (NSData *)_sourceApplicationAuditData
3153 {
3154     return _private->sourceApplicationAuditData.get();
3155 }
3156
3157 - (void)_setFontFallbackPrefersPictographs:(BOOL)flag
3158 {
3159     if (_private->page)
3160         _private->page->settings().setFontFallbackPrefersPictographs(flag);
3161 }
3162
3163 @end
3164
3165 @implementation _WebSafeForwarder
3166
3167 // Used to send messages to delegates that implement informal protocols.
3168
3169 - (id)initWithTarget:(id)t defaultTarget:(id)dt
3170 {
3171     self = [super init];
3172     if (!self)
3173         return nil;
3174     target = t; // Non retained.
3175     defaultTarget = dt;
3176     return self;
3177 }
3178
3179 - (void)forwardInvocation:(NSInvocation *)invocation
3180 {
3181     if ([target respondsToSelector:[invocation selector]]) {
3182         @try {
3183             [invocation invokeWithTarget:target];
3184         } @catch(id exception) {
3185             ReportDiscardedDelegateException([invocation selector], exception);
3186         }
3187         return;
3188     }
3189
3190     if ([defaultTarget respondsToSelector:[invocation selector]])
3191         [invocation invokeWithTarget:defaultTarget];
3192
3193     // Do nothing quietly if method not implemented.
3194 }
3195
3196 - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
3197 {
3198     return [defaultTarget methodSignatureForSelector:aSelector];
3199 }
3200
3201 @end
3202
3203 @implementation WebView
3204
3205 + (void)initialize
3206 {
3207     static BOOL initialized = NO;
3208     if (initialized)
3209         return;
3210     initialized = YES;
3211
3212     InitWebCoreSystemInterface();
3213     JSC::initializeThreading();
3214     WTF::initializeMainThreadToProcessMainThread();
3215     WebCore::RunLoop::initializeMainRunLoop();
3216
3217     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_applicationWillTerminate) name:NSApplicationWillTerminateNotification object:NSApp];
3218     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_cacheModelChangedNotification:) name:WebPreferencesCacheModelChangedInternalNotification object:nil];
3219     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesRemovedNotification:) name:WebPreferencesRemovedNotification object:nil];
3220
3221     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
3222
3223 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
3224     [defaults registerDefaults:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:WebKitKerningAndLigaturesEnabledByDefaultDefaultsKey]];
3225 #endif
3226
3227     continuousSpellCheckingEnabled = [defaults boolForKey:WebContinuousSpellCheckingEnabled];
3228     grammarCheckingEnabled = [defaults boolForKey:WebGrammarCheckingEnabled];
3229
3230     Font::setDefaultTypesettingFeatures([defaults boolForKey:WebKitKerningAndLigaturesEnabledByDefaultDefaultsKey] ? Kerning | Ligatures : 0);
3231
3232     automaticQuoteSubstitutionEnabled = [self _shouldAutomaticQuoteSubstitutionBeEnabled];
3233     automaticLinkDetectionEnabled = [defaults boolForKey:WebAutomaticLinkDetectionEnabled];
3234     automaticDashSubstitutionEnabled = [self _shouldAutomaticDashSubstitutionBeEnabled];
3235     automaticTextReplacementEnabled = [self _shouldAutomaticTextReplacementBeEnabled];
3236     automaticSpellingCorrectionEnabled = [self _shouldAutomaticSpellingCorrectionBeEnabled];
3237
3238     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_didChangeAutomaticTextReplacementEnabled:)
3239         name:NSSpellCheckerDidChangeAutomaticTextReplacementNotification object:nil];
3240     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_didChangeAutomaticSpellingCorrectionEnabled:)
3241         name:NSSpellCheckerDidChangeAutomaticSpellingCorrectionNotification object:nil];
3242
3243 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
3244     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_didChangeAutomaticQuoteSubstitutionEnabled:)
3245         name:NSSpellCheckerDidChangeAutomaticQuoteSubstitutionNotification object:nil];
3246     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_didChangeAutomaticDashSubstitutionEnabled:)
3247         name:NSSpellCheckerDidChangeAutomaticDashSubstitutionNotification object:nil];
3248 #endif
3249 }
3250
3251 + (BOOL)_shouldAutomaticTextReplacementBeEnabled
3252 {
3253     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
3254     if (![defaults objectForKey:WebAutomaticTextReplacementEnabled])
3255         return [NSSpellChecker isAutomaticTextReplacementEnabled];
3256     return [defaults boolForKey:WebAutomaticTextReplacementEnabled];
3257 }
3258
3259 + (void)_didChangeAutomaticTextReplacementEnabled:(NSNotification *)notification
3260 {
3261     automaticTextReplacementEnabled = [self _shouldAutomaticTextReplacementBeEnabled];
3262     [[NSSpellChecker sharedSpellChecker] updatePanels];
3263 }
3264
3265 + (BOOL)_shouldAutomaticSpellingCorrectionBeEnabled
3266 {
3267     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
3268     if (![defaults objectForKey:WebAutomaticSpellingCorrectionEnabled])
3269         return [NSSpellChecker isAutomaticTextReplacementEnabled];
3270     return [defaults boolForKey:WebAutomaticSpellingCorrectionEnabled];
3271 }
3272
3273 + (void)_didChangeAutomaticSpellingCorrectionEnabled:(NSNotification *)notification
3274 {
3275     automaticSpellingCorrectionEnabled = [self _shouldAutomaticSpellingCorrectionBeEnabled];
3276     [[NSSpellChecker sharedSpellChecker] updatePanels];
3277 }
3278
3279 + (BOOL)_shouldAutomaticQuoteSubstitutionBeEnabled
3280 {
3281     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
3282 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
3283     if (![defaults objectForKey:WebAutomaticQuoteSubstitutionEnabled])
3284         return [NSSpellChecker isAutomaticQuoteSubstitutionEnabled];
3285 #endif
3286     return [defaults boolForKey:WebAutomaticQuoteSubstitutionEnabled];
3287 }
3288
3289 + (BOOL)_shouldAutomaticDashSubstitutionBeEnabled
3290 {
3291     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
3292 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
3293     if (![defaults objectForKey:WebAutomaticDashSubstitutionEnabled])
3294         return [NSSpellChecker isAutomaticDashSubstitutionEnabled];
3295 #endif
3296     return [defaults boolForKey:WebAutomaticDashSubstitutionEnabled];
3297 }
3298
3299 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
3300 + (void)_didChangeAutomaticQuoteSubstitutionEnabled:(NSNotification *)notification
3301 {
3302     automaticQuoteSubstitutionEnabled = [self _shouldAutomaticQuoteSubstitutionBeEnabled];
3303     [[NSSpellChecker sharedSpellChecker] updatePanels];
3304 }
3305
3306 + (void)_didChangeAutomaticDashSubstitutionEnabled:(NSNotification *)notification
3307 {
3308     automaticDashSubstitutionEnabled = [self _shouldAutomaticDashSubstitutionBeEnabled];
3309     [[NSSpellChecker sharedSpellChecker] updatePanels];
3310 }
3311 #endif
3312
3313 + (void)_applicationWillTerminate
3314 {   
3315     applicationIsTerminating = YES;
3316
3317     if (fastDocumentTeardownEnabled())
3318         [self closeAllWebViews];
3319
3320     if (!pluginDatabaseClientCount)
3321         [WebPluginDatabase closeSharedDatabase];
3322
3323     PageGroup::closeLocalStorage();
3324 }
3325
3326 + (BOOL)_canShowMIMEType:(NSString *)MIMEType allowingPlugins:(BOOL)allowPlugins
3327 {
3328     return [self _viewClass:nil andRepresentationClass:nil forMIMEType:MIMEType allowingPlugins:allowPlugins];
3329 }
3330
3331 + (BOOL)canShowMIMEType:(NSString *)MIMEType
3332 {
3333     return [self _canShowMIMEType:MIMEType allowingPlugins:YES];
3334 }
3335
3336 - (BOOL)_canShowMIMEType:(NSString *)MIMEType
3337 {
3338     return [[self class] _canShowMIMEType:MIMEType allowingPlugins:[_private->preferences arePlugInsEnabled]];
3339 }
3340
3341 - (WebBasePluginPackage *)_pluginForMIMEType:(NSString *)MIMEType
3342 {
3343     if (![_private->preferences arePlugInsEnabled])
3344         return nil;
3345
3346     WebBasePluginPackage *pluginPackage = [[WebPluginDatabase sharedDatabase] pluginForMIMEType:MIMEType];
3347     if (pluginPackage)
3348         return pluginPackage;
3349     
3350     if (_private->pluginDatabase)
3351         return [_private->pluginDatabase pluginForMIMEType:MIMEType];
3352     
3353     return nil;
3354 }
3355
3356 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
3357 - (WebBasePluginPackage *)_videoProxyPluginForMIMEType:(NSString *)MIMEType
3358 {
3359     WebBasePluginPackage *pluginPackage = [[WebPluginDatabase sharedDatabase] pluginForMIMEType:MIMEType];
3360     if (pluginPackage)
3361         return pluginPackage;
3362
3363     if (_private->pluginDatabase)
3364         return [_private->pluginDatabase pluginForMIMEType:MIMEType];
3365
3366     return nil;
3367 }
3368 #endif
3369
3370 - (WebBasePluginPackage *)_pluginForExtension:(NSString *)extension
3371 {
3372     if (![_private->preferences arePlugInsEnabled])
3373         return nil;
3374
3375     WebBasePluginPackage *pluginPackage = [[WebPluginDatabase sharedDatabase] pluginForExtension:extension];
3376     if (pluginPackage)
3377         return pluginPackage;
3378     
3379     if (_private->pluginDatabase)
3380         return [_private->pluginDatabase pluginForExtension:extension];
3381     
3382     return nil;
3383 }
3384
3385 - (void)addPluginInstanceView:(NSView *)view
3386 {
3387     if (!_private->pluginDatabase)
3388         _private->pluginDatabase = [[WebPluginDatabase alloc] init];
3389     [_private->pluginDatabase addPluginInstanceView:view];
3390 }
3391
3392 - (void)removePluginInstanceView:(NSView *)view
3393 {
3394     if (_private->pluginDatabase)
3395         [_private->pluginDatabase removePluginInstanceView:view];    
3396 }
3397
3398 - (void)removePluginInstanceViewsFor:(WebFrame*)webFrame 
3399 {
3400     if (_private->pluginDatabase)
3401         [_private->pluginDatabase removePluginInstanceViewsFor:webFrame];    
3402 }
3403
3404 - (BOOL)_isMIMETypeRegisteredAsPlugin:(NSString *)MIMEType
3405 {
3406     if (![_private->preferences arePlugInsEnabled])
3407         return NO;
3408
3409     if ([[WebPluginDatabase sharedDatabase] isMIMETypeRegistered:MIMEType])
3410         return YES;
3411         
3412     if (_private->pluginDatabase && [_private->pluginDatabase isMIMETypeRegistered:MIMEType])
3413         return YES;
3414     
3415     return NO;
3416 }
3417
3418 + (BOOL)canShowMIMETypeAsHTML:(NSString *)MIMEType
3419 {
3420     return [WebFrameView _canShowMIMETypeAsHTML:MIMEType];
3421 }
3422
3423 + (NSArray *)MIMETypesShownAsHTML
3424 {
3425     NSMutableDictionary *viewTypes = [WebFrameView _viewTypesAllowImageTypeOmission:YES];
3426     NSEnumerator *enumerator = [viewTypes keyEnumerator];
3427     id key;
3428     NSMutableArray *array = [[[NSMutableArray alloc] init] autorelease];
3429     
3430     while ((key = [enumerator nextObject])) {
3431         if ([viewTypes objectForKey:key] == [WebHTMLView class])
3432             [array addObject:key];
3433     }
3434     
3435     return array;
3436 }
3437
3438 + (void)setMIMETypesShownAsHTML:(NSArray *)MIMETypes
3439 {
3440     NSDictionary *viewTypes = [[WebFrameView _viewTypesAllowImageTypeOmission:YES] copy];
3441     NSEnumerator *enumerator = [viewTypes keyEnumerator];
3442     id key;
3443     while ((key = [enumerator nextObject])) {
3444         if ([viewTypes objectForKey:key] == [WebHTMLView class])
3445             [WebView _unregisterViewClassAndRepresentationClassForMIMEType:key];
3446     }
3447     
3448     int i, count = [MIMETypes count];
3449     for (i = 0; i < count; i++) {
3450         [WebView registerViewClass:[WebHTMLView class] 
3451                 representationClass:[WebHTMLRepresentation class] 
3452                 forMIMEType:[MIMETypes objectAtIndex:i]];
3453     }
3454     [viewTypes release];
3455 }
3456
3457 + (NSURL *)URLFromPasteboard:(NSPasteboard *)pasteboard
3458 {
3459     return [pasteboard _web_bestURL];
3460 }
3461
3462 + (NSString *)URLTitleFromPasteboard:(NSPasteboard *)pasteboard
3463 {
3464     return [pasteboard stringForType:WebURLNamePboardType];
3465 }
3466
3467 + (void)registerURLSchemeAsLocal:(NSString *)protocol
3468 {
3469     SchemeRegistry::registerURLSchemeAsLocal(protocol);
3470 }
3471
3472 - (id)_initWithArguments:(NSDictionary *) arguments
3473 {
3474     NSCoder *decoder = [arguments objectForKey:@"decoder"];
3475     if (decoder) {
3476         self = [self initWithCoder:decoder];
3477     } else {
3478         ASSERT([arguments objectForKey:@"frame"]);
3479         NSValue *frameValue = [arguments objectForKey:@"frame"];
3480         NSRect frame = (frameValue ? [frameValue rectValue] : NSZeroRect);
3481         NSString *frameName = [arguments objectForKey:@"frameName"];
3482         NSString *groupName = [arguments objectForKey:@"groupName"];
3483         self = [self initWithFrame:frame frameName:frameName groupName:groupName];
3484     }
3485
3486     return self;
3487 }
3488
3489 static bool clientNeedsWebViewInitThreadWorkaround()
3490 {
3491     if (WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_WEBVIEW_INIT_THREAD_WORKAROUND))
3492         return false;
3493
3494     NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
3495
3496     // Installer.
3497     if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.installer"])
3498         return true;
3499
3500     // Automator.
3501     if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.Automator"])
3502         return true;
3503
3504     // Automator Runner.
3505     if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.AutomatorRunner"])
3506         return true;
3507
3508     // Automator workflows.
3509     if ([bundleIdentifier _webkit_hasCaseInsensitivePrefix:@"com.apple.Automator."])
3510         return true;
3511
3512     return false;
3513 }
3514
3515 static bool needsWebViewInitThreadWorkaround()
3516 {
3517     static bool isOldClient = clientNeedsWebViewInitThreadWorkaround();
3518     return isOldClient && !pthread_main_np();
3519 }
3520
3521 - (id)initWithFrame:(NSRect)f
3522 {
3523     return [self initWithFrame:f frameName:nil groupName:nil];
3524 }
3525
3526 - (id)initWithFrame:(NSRect)f frameName:(NSString *)frameName groupName:(NSString *)groupName
3527 {
3528     if (needsWebViewInitThreadWorkaround())
3529         return [[self _webkit_invokeOnMainThread] initWithFrame:f frameName:frameName groupName:groupName];
3530
3531     WebCoreThreadViolationCheckRoundTwo();
3532     return [self _initWithFrame:f frameName:frameName groupName:groupName usesDocumentViews:YES];
3533 }
3534
3535 - (id)initWithCoder:(NSCoder *)decoder
3536 {
3537     if (needsWebViewInitThreadWorkaround())
3538         return [[self _webkit_invokeOnMainThread] initWithCoder:decoder];
3539
3540     WebCoreThreadViolationCheckRoundTwo();
3541     WebView *result = nil;
3542
3543     @try {
3544         NSString *frameName;
3545         NSString *groupName;
3546         WebPreferences *preferences;
3547         BOOL useBackForwardList = NO;
3548         BOOL allowsUndo = YES;
3549         
3550         result = [super initWithCoder:decoder];
3551         result->_private = [[WebViewPrivate alloc] init];
3552
3553         // We don't want any of the archived subviews. The subviews will always
3554         // be created in _commonInitializationFrameName:groupName:.
3555         [[result subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
3556
3557         if ([decoder allowsKeyedCoding]) {
3558             frameName = [decoder decodeObjectForKey:@"FrameName"];
3559             groupName = [decoder decodeObjectForKey:@"GroupName"];
3560             preferences = [decoder decodeObjectForKey:@"Preferences"];
3561             useBackForwardList = [decoder decodeBoolForKey:@"UseBackForwardList"];
3562             if ([decoder containsValueForKey:@"AllowsUndo"])
3563                 allowsUndo = [decoder decodeBoolForKey:@"AllowsUndo"];
3564         } else {
3565             int version;
3566             [decoder decodeValueOfObjCType:@encode(int) at:&version];
3567             frameName = [decoder decodeObject];
3568             groupName = [decoder decodeObject];
3569             preferences = [decoder decodeObject];
3570             if (version > 1)
3571                 [decoder decodeValuesOfObjCTypes:"c", &useBackForwardList];
3572             // The allowsUndo field is no longer written out in encodeWithCoder, but since there are
3573             // version 3 NIBs that have this field encoded, we still need to read it in.
3574             if (version == 3)
3575                 [decoder decodeValuesOfObjCTypes:"c", &allowsUndo];
3576         }
3577
3578         if (![frameName isKindOfClass:[NSString class]])
3579             frameName = nil;
3580         if (![groupName isKindOfClass:[NSString class]])
3581             groupName = nil;
3582         if (![preferences isKindOfClass:[WebPreferences class]])
3583             preferences = nil;
3584
3585         LOG(Encoding, "FrameName = %@, GroupName = %@, useBackForwardList = %d\n", frameName, groupName, (int)useBackForwardList);
3586         [result _commonInitializationWithFrameName:frameName groupName:groupName];
3587         static_cast<BackForwardList*>([result page]->backForwardClient())->setEnabled(useBackForwardList);
3588         result->_private->allowsUndo = allowsUndo;
3589         if (preferences)
3590             [result setPreferences:preferences];
3591     } @catch (NSException *localException) {
3592         result = nil;
3593         [self release];
3594     }
3595
3596     return result;
3597 }
3598
3599 - (void)encodeWithCoder:(NSCoder *)encoder
3600 {
3601     // Set asside the subviews before we archive. We don't want to archive any subviews.
3602     // The subviews will always be created in _commonInitializationFrameName:groupName:.
3603     id originalSubviews = _subviews;
3604     _subviews = nil;
3605
3606     [super encodeWithCoder:encoder];
3607
3608     // Restore the subviews we set aside.
3609     _subviews = originalSubviews;
3610
3611     BOOL useBackForwardList = _private->page && static_cast<BackForwardList*>(_private->page->backForwardClient())->enabled();
3612     if ([encoder allowsKeyedCoding]) {
3613         [encoder encodeObject:[[self mainFrame] name] forKey:@"FrameName"];
3614         [encoder encodeObject:[self groupName] forKey:@"GroupName"];
3615         [encoder encodeObject:[self preferences] forKey:@"Preferences"];