blob: 805cdb900e1fcc9968f493188244e28716d87533 [file] [log] [blame]
/*
* Copyright (C) 2005-2012 Apple Inc. All rights reserved.
* Copyright (C) 2006 David Smith (catfish.man@gmail.com)
* Copyright (C) 2010 Igalia S.L
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "WebViewInternal.h"
#import "WebViewData.h"
#import "DOMCSSStyleDeclarationInternal.h"
#import "DOMDocumentInternal.h"
#import "DOMNodeInternal.h"
#import "DOMRangeInternal.h"
#import "WebAlternativeTextClient.h"
#import "WebApplicationCache.h"
#import "WebBackForwardListInternal.h"
#import "WebBaseNetscapePluginView.h"
#import "WebCache.h"
#import "WebChromeClient.h"
#import "WebContextMenuClient.h"
#import "WebDOMOperationsPrivate.h"
#import "WebDataSourceInternal.h"
#import "WebDatabaseManagerPrivate.h"
#import "WebDefaultEditingDelegate.h"
#import "WebDefaultPolicyDelegate.h"
#import "WebDefaultUIDelegate.h"
#import "WebDelegateImplementationCaching.h"
#import "WebDeviceOrientationClient.h"
#import "WebDeviceOrientationProvider.h"
#import "WebDocument.h"
#import "WebDocumentInternal.h"
#import "WebDownload.h"
#import "WebDownloadInternal.h"
#import "WebDragClient.h"
#import "WebDynamicScrollBarsViewInternal.h"
#import "WebEditingDelegate.h"
#import "WebEditorClient.h"
#import "WebFormDelegatePrivate.h"
#import "WebFrameInternal.h"
#import "WebFrameNetworkingContext.h"
#import "WebFrameViewInternal.h"
#import "WebFullScreenController.h"
#import "WebGeolocationClient.h"
#import "WebGeolocationPositionInternal.h"
#import "WebHTMLRepresentation.h"
#import "WebHTMLViewInternal.h"
#import "WebHistoryItemInternal.h"
#import "WebIconDatabaseInternal.h"
#import "WebInspector.h"
#import "WebInspectorClient.h"
#import "WebKitErrors.h"
#import "WebKitFullScreenListener.h"
#import "WebKitLogging.h"
#import "WebKitNSStringExtras.h"
#import "WebKitStatisticsPrivate.h"
#import "WebKitSystemBits.h"
#import "WebKitVersionChecks.h"
#import "WebLocalizableStrings.h"
#import "WebNSDataExtras.h"
#import "WebNSDataExtrasPrivate.h"
#import "WebNSDictionaryExtras.h"
#import "WebNSEventExtras.h"
#import "WebNSObjectExtras.h"
#import "WebNSPasteboardExtras.h"
#import "WebNSPrintOperationExtras.h"
#import "WebNSURLExtras.h"
#import "WebNSURLRequestExtras.h"
#import "WebNSViewExtras.h"
#import "WebNodeHighlight.h"
#import "WebNotificationClient.h"
#import "WebPDFView.h"
#import "WebPanelAuthenticationHandler.h"
#import "WebPlatformStrategies.h"
#import "WebPluginDatabase.h"
#import "WebPolicyDelegate.h"
#import "WebPreferenceKeysPrivate.h"
#import "WebPreferencesPrivate.h"
#import "WebScriptDebugDelegate.h"
#import "WebScriptWorldInternal.h"
#import "WebStorageManagerInternal.h"
#import "WebSystemInterface.h"
#import "WebTextCompletionController.h"
#import "WebTextIterator.h"
#import "WebUIDelegate.h"
#import "WebUIDelegatePrivate.h"
#import <CoreFoundation/CFSet.h>
#import <Foundation/NSURLConnection.h>
#import <JavaScriptCore/APICast.h>
#import <JavaScriptCore/JSValueRef.h>
#import <WebCore/AlternativeTextUIController.h>
#import <WebCore/AnimationController.h>
#import <WebCore/ApplicationCacheStorage.h>
#import <WebCore/BackForwardListImpl.h>
#import <WebCore/MemoryCache.h>
#import <WebCore/ColorMac.h>
#import <WebCore/Cursor.h>
#import <WebCore/DatabaseManager.h>
#import <WebCore/Document.h>
#import <WebCore/DocumentLoader.h>
#import <WebCore/DragController.h>
#import <WebCore/DragData.h>
#import <WebCore/DragSession.h>
#import <WebCore/Editor.h>
#import <WebCore/EventHandler.h>
#import <WebCore/ExceptionHandlers.h>
#import <WebCore/FocusController.h>
#import <WebCore/Frame.h>
#import <WebCore/FrameLoader.h>
#import <WebCore/FrameSelection.h>
#import <WebCore/FrameTree.h>
#import <WebCore/FrameView.h>
#import <WebCore/GCController.h>
#import <WebCore/GeolocationController.h>
#import <WebCore/GeolocationError.h>
#import <WebCore/HTMLMediaElement.h>
#import <WebCore/HTMLNames.h>
#import <WebCore/HistoryController.h>
#import <WebCore/HistoryItem.h>
#import <WebCore/IconDatabase.h>
#import <WebCore/InitializeLogging.h>
#import <WebCore/JSCSSStyleDeclaration.h>
#import <WebCore/JSDocument.h>
#import <WebCore/JSElement.h>
#import <WebCore/JSNodeList.h>
#import <WebCore/JSNotification.h>
#import <WebCore/MemoryPressureHandler.h>
#import <WebCore/MIMETypeRegistry.h>
#import <WebCore/NodeList.h>
#import <WebCore/Notification.h>
#import <WebCore/NotificationController.h>
#import <WebCore/Page.h>
#import <WebCore/PageCache.h>
#import <WebCore/PageGroup.h>
#import <WebCore/PlatformEventFactoryMac.h>
#import <WebCore/ProgressTracker.h>
#import <WebCore/RenderView.h>
#import <WebCore/RenderWidget.h>
#import <WebCore/ResourceHandle.h>
#import <WebCore/ResourceLoadScheduler.h>
#import <WebCore/ResourceRequest.h>
#import <WebCore/RunLoop.h>
#import <WebCore/RuntimeApplicationChecks.h>
#import <WebCore/RuntimeEnabledFeatures.h>
#import <WebCore/SchemeRegistry.h>
#import <WebCore/ScriptController.h>
#import <WebCore/ScriptValue.h>
#import <WebCore/SecurityOrigin.h>
#import <WebCore/SecurityPolicy.h>
#import <WebCore/Settings.h>
#import <WebCore/StylePropertySet.h>
#import <WebCore/SystemVersionMac.h>
#import <WebCore/TextResourceDecoder.h>
#import <WebCore/ThreadCheck.h>
#import <WebCore/WebCoreObjCExtras.h>
#import <WebCore/WebCoreView.h>
#import <WebCore/WebVideoFullscreenController.h>
#import <WebCore/Widget.h>
#import <WebKit/DOM.h>
#import <WebKit/DOMExtensions.h>
#import <WebKit/DOMPrivate.h>
#import <WebKitSystemInterface.h>
#import <mach-o/dyld.h>
#import <objc/objc-auto.h>
#import <objc/runtime.h>
#import <runtime/ArrayPrototype.h>
#import <runtime/DateInstance.h>
#import <runtime/InitializeThreading.h>
#import <runtime/JSLock.h>
#import <runtime/JSCJSValue.h>
#import <wtf/Assertions.h>
#import <wtf/HashTraits.h>
#import <wtf/MainThread.h>
#import <wtf/RefCountedLeakCounter.h>
#import <wtf/RefPtr.h>
#import <wtf/StdLibExtras.h>
#if ENABLE(DASHBOARD_SUPPORT)
#import <WebKit/WebDashboardRegion.h>
#endif
#if USE(GLIB)
#import <glib.h>
#endif
@interface NSSpellChecker (WebNSSpellCheckerDetails)
- (void)_preflightChosenSpellServer;
@end
@interface NSView (WebNSViewDetails)
- (NSView *)_hitTest:(NSPoint *)aPoint dragTypes:(NSSet *)types;
- (void)_autoscrollForDraggingInfo:(id)dragInfo timeDelta:(NSTimeInterval)repeatDelta;
- (BOOL)_shouldAutoscrollForDraggingInfo:(id)dragInfo;
@end
@interface NSWindow (WebNSWindowDetails)
- (id)_oldFirstResponderBeforeBecoming;
- (void)_enableScreenUpdatesIfNeeded;
- (BOOL)_wrapsCarbonWindow;
- (BOOL)_hasKeyAppearance;
@end
using namespace WebCore;
using namespace JSC;
#if defined(__ppc__) || defined(__ppc64__)
#define PROCESSOR "PPC"
#elif defined(__i386__) || defined(__x86_64__)
#define PROCESSOR "Intel"
#else
#error Unknown architecture
#endif
#define FOR_EACH_RESPONDER_SELECTOR(macro) \
macro(alignCenter) \
macro(alignJustified) \
macro(alignLeft) \
macro(alignRight) \
macro(capitalizeWord) \
macro(centerSelectionInVisibleArea) \
macro(changeAttributes) \
macro(changeBaseWritingDirection) \
macro(changeBaseWritingDirectionToLTR) \
macro(changeBaseWritingDirectionToRTL) \
macro(changeColor) \
macro(changeDocumentBackgroundColor) \
macro(changeFont) \
macro(changeSpelling) \
macro(checkSpelling) \
macro(complete) \
macro(copy) \
macro(copyFont) \
macro(cut) \
macro(delete) \
macro(deleteBackward) \
macro(deleteBackwardByDecomposingPreviousCharacter) \
macro(deleteForward) \
macro(deleteToBeginningOfLine) \
macro(deleteToBeginningOfParagraph) \
macro(deleteToEndOfLine) \
macro(deleteToEndOfParagraph) \
macro(deleteToMark) \
macro(deleteWordBackward) \
macro(deleteWordForward) \
macro(ignoreSpelling) \
macro(indent) \
macro(insertBacktab) \
macro(insertLineBreak) \
macro(insertNewline) \
macro(insertNewlineIgnoringFieldEditor) \
macro(insertParagraphSeparator) \
macro(insertTab) \
macro(insertTabIgnoringFieldEditor) \
macro(lowercaseWord) \
macro(makeBaseWritingDirectionLeftToRight) \
macro(makeBaseWritingDirectionRightToLeft) \
macro(makeTextWritingDirectionLeftToRight) \
macro(makeTextWritingDirectionNatural) \
macro(makeTextWritingDirectionRightToLeft) \
macro(moveBackward) \
macro(moveBackwardAndModifySelection) \
macro(moveDown) \
macro(moveDownAndModifySelection) \
macro(moveForward) \
macro(moveForwardAndModifySelection) \
macro(moveLeft) \
macro(moveLeftAndModifySelection) \
macro(moveParagraphBackwardAndModifySelection) \
macro(moveParagraphForwardAndModifySelection) \
macro(moveRight) \
macro(moveRightAndModifySelection) \
macro(moveToBeginningOfDocument) \
macro(moveToBeginningOfDocumentAndModifySelection) \
macro(moveToBeginningOfLine) \
macro(moveToBeginningOfLineAndModifySelection) \
macro(moveToBeginningOfParagraph) \
macro(moveToBeginningOfParagraphAndModifySelection) \
macro(moveToBeginningOfSentence) \
macro(moveToBeginningOfSentenceAndModifySelection) \
macro(moveToEndOfDocument) \
macro(moveToEndOfDocumentAndModifySelection) \
macro(moveToEndOfLine) \
macro(moveToEndOfLineAndModifySelection) \
macro(moveToEndOfParagraph) \
macro(moveToEndOfParagraphAndModifySelection) \
macro(moveToEndOfSentence) \
macro(moveToEndOfSentenceAndModifySelection) \
macro(moveToLeftEndOfLine) \
macro(moveToLeftEndOfLineAndModifySelection) \
macro(moveToRightEndOfLine) \
macro(moveToRightEndOfLineAndModifySelection) \
macro(moveUp) \
macro(moveUpAndModifySelection) \
macro(moveWordBackward) \
macro(moveWordBackwardAndModifySelection) \
macro(moveWordForward) \
macro(moveWordForwardAndModifySelection) \
macro(moveWordLeft) \
macro(moveWordLeftAndModifySelection) \
macro(moveWordRight) \
macro(moveWordRightAndModifySelection) \
macro(orderFrontSubstitutionsPanel) \
macro(outdent) \
macro(overWrite) \
macro(pageDown) \
macro(pageDownAndModifySelection) \
macro(pageUp) \
macro(pageUpAndModifySelection) \
macro(paste) \
macro(pasteAsPlainText) \
macro(pasteAsRichText) \
macro(pasteFont) \
macro(performFindPanelAction) \
macro(scrollLineDown) \
macro(scrollLineUp) \
macro(scrollPageDown) \
macro(scrollPageUp) \
macro(scrollToBeginningOfDocument) \
macro(scrollToEndOfDocument) \
macro(selectAll) \
macro(selectLine) \
macro(selectParagraph) \
macro(selectSentence) \
macro(selectToMark) \
macro(selectWord) \
macro(setMark) \
macro(showGuessPanel) \
macro(startSpeaking) \
macro(stopSpeaking) \
macro(subscript) \
macro(superscript) \
macro(swapWithMark) \
macro(takeFindStringFromSelection) \
macro(toggleBaseWritingDirection) \
macro(transpose) \
macro(underline) \
macro(unscript) \
macro(uppercaseWord) \
macro(yank) \
macro(yankAndSelect) \
#define WebKitOriginalTopPrintingMarginKey @"WebKitOriginalTopMargin"
#define WebKitOriginalBottomPrintingMarginKey @"WebKitOriginalBottomMargin"
#define KeyboardUIModeDidChangeNotification @"com.apple.KeyboardUIModeDidChange"
#define AppleKeyboardUIMode CFSTR("AppleKeyboardUIMode")
#define UniversalAccessDomain CFSTR("com.apple.universalaccess")
static BOOL s_didSetCacheModel;
static WebCacheModel s_cacheModel = WebCacheModelDocumentViewer;
#ifndef NDEBUG
static const char webViewIsOpen[] = "At least one WebView is still open.";
#endif
@interface NSObject (WebValidateWithoutDelegate)
- (BOOL)validateUserInterfaceItemWithoutDelegate:(id <NSValidatedUserInterfaceItem>)item;
@end
@interface _WebSafeForwarder : NSObject
{
id target; // Non-retained. Don't retain delegates.
id defaultTarget;
}
- (id)initWithTarget:(id)target defaultTarget:(id)defaultTarget;
@end
FindOptions coreOptions(WebFindOptions options)
{
return (options & WebFindOptionsCaseInsensitive ? CaseInsensitive : 0)
| (options & WebFindOptionsAtWordStarts ? AtWordStarts : 0)
| (options & WebFindOptionsTreatMedialCapitalAsWordStart ? TreatMedialCapitalAsWordStart : 0)
| (options & WebFindOptionsBackwards ? Backwards : 0)
| (options & WebFindOptionsWrapAround ? WrapAround : 0)
| (options & WebFindOptionsStartInSelection ? StartInSelection : 0);
}
LayoutMilestones coreLayoutMilestones(WebLayoutMilestones milestones)
{
return (milestones & WebDidFirstLayout ? DidFirstLayout : 0)
| (milestones & WebDidFirstVisuallyNonEmptyLayout ? DidFirstVisuallyNonEmptyLayout : 0)
| (milestones & WebDidHitRelevantRepaintedObjectsAreaThreshold ? DidHitRelevantRepaintedObjectsAreaThreshold : 0);
}
WebLayoutMilestones kitLayoutMilestones(LayoutMilestones milestones)
{
return (milestones & DidFirstLayout ? WebDidFirstLayout : 0)
| (milestones & DidFirstVisuallyNonEmptyLayout ? WebDidFirstVisuallyNonEmptyLayout : 0)
| (milestones & DidHitRelevantRepaintedObjectsAreaThreshold ? WebDidHitRelevantRepaintedObjectsAreaThreshold : 0);
}
static PageVisibilityState core(WebPageVisibilityState visibilityState)
{
switch (visibilityState) {
case WebPageVisibilityStateVisible:
return PageVisibilityStateVisible;
case WebPageVisibilityStateHidden:
return PageVisibilityStateHidden;
case WebPageVisibilityStatePrerender:
return PageVisibilityStatePrerender;
case WebPageVisibilityStatePreview:
return PageVisibilityStatePreview;
}
ASSERT_NOT_REACHED();
return PageVisibilityStateVisible;
}
@interface WebView (WebFileInternal)
- (float)_deviceScaleFactor;
- (BOOL)_isLoading;
- (WebFrameView *)_frameViewAtWindowPoint:(NSPoint)point;
- (WebFrame *)_focusedFrame;
+ (void)_preflightSpellChecker;
- (BOOL)_continuousCheckingAllowed;
- (NSResponder *)_responderForResponderOperations;
#if USE(GLIB)
- (void)_clearGlibLoopObserver;
#endif
@end
NSString *WebElementDOMNodeKey = @"WebElementDOMNode";
NSString *WebElementFrameKey = @"WebElementFrame";
NSString *WebElementImageKey = @"WebElementImage";
NSString *WebElementImageAltStringKey = @"WebElementImageAltString";
NSString *WebElementImageRectKey = @"WebElementImageRect";
NSString *WebElementImageURLKey = @"WebElementImageURL";
NSString *WebElementIsSelectedKey = @"WebElementIsSelected";
NSString *WebElementLinkLabelKey = @"WebElementLinkLabel";
NSString *WebElementLinkTargetFrameKey = @"WebElementTargetFrame";
NSString *WebElementLinkTitleKey = @"WebElementLinkTitle";
NSString *WebElementLinkURLKey = @"WebElementLinkURL";
NSString *WebElementMediaURLKey = @"WebElementMediaURL";
NSString *WebElementSpellingToolTipKey = @"WebElementSpellingToolTip";
NSString *WebElementTitleKey = @"WebElementTitle";
NSString *WebElementLinkIsLiveKey = @"WebElementLinkIsLive";
NSString *WebElementIsInScrollBarKey = @"WebElementIsInScrollBar";
NSString *WebElementIsContentEditableKey = @"WebElementIsContentEditableKey";
NSString *WebViewProgressStartedNotification = @"WebProgressStartedNotification";
NSString *WebViewProgressEstimateChangedNotification = @"WebProgressEstimateChangedNotification";
NSString *WebViewProgressFinishedNotification = @"WebProgressFinishedNotification";
NSString * const WebViewDidBeginEditingNotification = @"WebViewDidBeginEditingNotification";
NSString * const WebViewDidChangeNotification = @"WebViewDidChangeNotification";
NSString * const WebViewDidEndEditingNotification = @"WebViewDidEndEditingNotification";
NSString * const WebViewDidChangeTypingStyleNotification = @"WebViewDidChangeTypingStyleNotification";
NSString * const WebViewDidChangeSelectionNotification = @"WebViewDidChangeSelectionNotification";
enum { WebViewVersion = 4 };
#define timedLayoutSize 4096
static NSMutableSet *schemesWithRepresentationsSet;
NSString *_WebCanGoBackKey = @"canGoBack";
NSString *_WebCanGoForwardKey = @"canGoForward";
NSString *_WebEstimatedProgressKey = @"estimatedProgress";
NSString *_WebIsLoadingKey = @"isLoading";
NSString *_WebMainFrameIconKey = @"mainFrameIcon";
NSString *_WebMainFrameTitleKey = @"mainFrameTitle";
NSString *_WebMainFrameURLKey = @"mainFrameURL";
NSString *_WebMainFrameDocumentKey = @"mainFrameDocument";
NSString *_WebViewDidStartAcceleratedCompositingNotification = @"_WebViewDidStartAcceleratedCompositing";
NSString *WebKitKerningAndLigaturesEnabledByDefaultDefaultsKey = @"WebKitKerningAndLigaturesEnabledByDefault";
@interface WebProgressItem : NSObject
{
@public
long long bytesReceived;
long long estimatedLength;
}
@end
@implementation WebProgressItem
@end
static BOOL continuousSpellCheckingEnabled;
static BOOL grammarCheckingEnabled;
static BOOL automaticQuoteSubstitutionEnabled;
static BOOL automaticLinkDetectionEnabled;
static BOOL automaticDashSubstitutionEnabled;
static BOOL automaticTextReplacementEnabled;
static BOOL automaticSpellingCorrectionEnabled;
@implementation WebView (AllWebViews)
static CFSetCallBacks NonRetainingSetCallbacks = {
0,
NULL,
NULL,
CFCopyDescription,
CFEqual,
CFHash
};
static CFMutableSetRef allWebViewsSet;
+ (void)_makeAllWebViewsPerformSelector:(SEL)selector
{
if (!allWebViewsSet)
return;
[(NSMutableSet *)allWebViewsSet makeObjectsPerformSelector:selector];
}
- (void)_removeFromAllWebViewsSet
{
if (allWebViewsSet)
CFSetRemoveValue(allWebViewsSet, self);
}
- (void)_addToAllWebViewsSet
{
if (!allWebViewsSet)
allWebViewsSet = CFSetCreateMutable(NULL, 0, &NonRetainingSetCallbacks);
CFSetSetValue(allWebViewsSet, self);
}
@end
@implementation WebView (WebPrivate)
static NSString *systemMarketingVersionForUserAgentString()
{
// Use underscores instead of dots because when we first added the Mac OS X version to the user agent string
// we were concerned about old DHTML libraries interpreting "4." as Netscape 4. That's no longer a concern for us
// but we're sticking with the underscores for compatibility with the format used by older versions of Safari.
return [systemMarketingVersion() stringByReplacingOccurrencesOfString:@"." withString:@"_"];
}
static NSString *createUserVisibleWebKitVersionString()
{
// If the version is 4 digits long or longer, then the first digit represents
// the version of the OS. Our user agent string should not include this first digit,
// so strip it off and report the rest as the version. <rdar://problem/4997547>
NSString *fullVersion = [[NSBundle bundleForClass:[WebView class]] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey];
NSRange nonDigitRange = [fullVersion rangeOfCharacterFromSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]];
if (nonDigitRange.location == NSNotFound && [fullVersion length] >= 4)
return [[fullVersion substringFromIndex:1] copy];
if (nonDigitRange.location != NSNotFound && nonDigitRange.location >= 4)
return [[fullVersion substringFromIndex:1] copy];
return [fullVersion copy];
}
+ (NSString *)_standardUserAgentWithApplicationName:(NSString *)applicationName
{
// Note: Do *not* move the initialization of osVersion nor webKitVersion into the declaration.
// Garbage collection won't correctly mark the global variable in that case <rdar://problem/5733674>.
static NSString *osVersion;
static NSString *webKitVersion;
if (!osVersion)
osVersion = [systemMarketingVersionForUserAgentString() retain];
if (!webKitVersion)
webKitVersion = createUserVisibleWebKitVersionString();
if ([applicationName length])
return [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; " PROCESSOR " Mac OS X %@) AppleWebKit/%@ (KHTML, like Gecko) %@", osVersion, webKitVersion, applicationName];
return [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; " PROCESSOR " Mac OS X %@) AppleWebKit/%@ (KHTML, like Gecko)", osVersion, webKitVersion];
}
+ (void)_reportException:(JSValueRef)exception inContext:(JSContextRef)context
{
if (!exception || !context)
return;
JSC::ExecState* execState = toJS(context);
JSLockHolder lock(execState);
// Make sure the context has a DOMWindow global object, otherwise this context didn't originate from a WebView.
if (!toJSDOMWindow(execState->lexicalGlobalObject()))
return;
reportException(execState, toJS(execState, exception));
}
static void WebKitInitializeApplicationCachePathIfNecessary()
{
static BOOL initialized = NO;
if (initialized)
return;
NSString *appName = [[NSBundle mainBundle] bundleIdentifier];
if (!appName)
appName = [[NSProcessInfo processInfo] processName];
ASSERT(appName);
NSString* cacheDir = [NSString _webkit_localCacheDirectoryWithBundleIdentifier:appName];
cacheStorage().setCacheDirectory(cacheDir);
initialized = YES;
}
static bool shouldEnableLoadDeferring()
{
return !applicationIsAdobeInstaller();
}
- (void)_dispatchPendingLoadRequests
{
resourceLoadScheduler()->servePendingRequests();
}
- (void)_registerDraggedTypes
{
NSArray *editableTypes = [WebHTMLView _insertablePasteboardTypes];
NSArray *URLTypes = [NSPasteboard _web_dragTypesForURL];
NSMutableSet *types = [[NSMutableSet alloc] initWithArray:editableTypes];
[types addObjectsFromArray:URLTypes];
[self registerForDraggedTypes:[types allObjects]];
[types release];
}
#if __MAC_OS_X_VERSION_MIN_REQUIRED == 1060
// This method should be removed once we no longer want to keep Safari 5.0.x working with nightly builds.
- (BOOL)_usesDocumentViews
{
return true;
}
#endif
static bool needsOutlookQuirksScript()
{
static bool isOutlookNeedingQuirksScript = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_HTML5_PARSER)
&& applicationIsMicrosoftOutlook();
return isOutlookNeedingQuirksScript;
}
static NSString *leakOutlookQuirksUserScriptContents()
{
NSString *scriptPath = [[NSBundle bundleForClass:[WebView class]] pathForResource:@"OutlookQuirksUserScript" ofType:@"js"];
NSStringEncoding encoding;
return [[NSString alloc] initWithContentsOfFile:scriptPath usedEncoding:&encoding error:0];
}
-(void)_injectOutlookQuirksScript
{
static NSString *outlookQuirksScriptContents = leakOutlookQuirksUserScriptContents();
core(self)->group().addUserScriptToWorld(core([WebScriptWorld world]),
outlookQuirksScriptContents, KURL(), Vector<String>(), Vector<String>(), InjectAtDocumentEnd, InjectInAllFrames);
}
static bool shouldRespectPriorityInCSSAttributeSetters()
{
static bool isIAdProducerNeedingAttributeSetterQuirk = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_CSS_ATTRIBUTE_SETTERS_IGNORING_PRIORITY)
&& [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.iAdProducer"];
return isIAdProducerNeedingAttributeSetterQuirk;
}
static bool shouldUseLegacyBackgroundSizeShorthandBehavior()
{
static bool shouldUseLegacyBackgroundSizeShorthandBehavior = applicationIsVersions()
&& !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_LEGACY_BACKGROUNDSIZE_SHORTHAND_BEHAVIOR);
return shouldUseLegacyBackgroundSizeShorthandBehavior;
}
- (void)_commonInitializationWithFrameName:(NSString *)frameName groupName:(NSString *)groupName
{
WebCoreThreadViolationCheckRoundTwo();
#ifndef NDEBUG
WTF::RefCountedLeakCounter::suppressMessages(webViewIsOpen);
#endif
WebPreferences *standardPreferences = [WebPreferences standardPreferences];
[standardPreferences willAddToWebView];
_private->preferences = [standardPreferences retain];
_private->mainFrameDocumentReady = NO;
_private->drawsBackground = YES;
_private->backgroundColor = [[NSColor colorWithDeviceWhite:1 alpha:1] retain];
_private->includesFlattenedCompositingLayersWhenDrawingToBitmap = YES;
NSRect f = [self frame];
WebFrameView *frameView = [[WebFrameView alloc] initWithFrame: NSMakeRect(0,0,f.size.width,f.size.height)];
[frameView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
[self addSubview:frameView];
[frameView release];
static bool didOneTimeInitialization = false;
if (!didOneTimeInitialization) {
#if !LOG_DISABLED
WebKitInitializeLoggingChannelsIfNecessary();
WebCore::initializeLoggingChannelsIfNecessary();
#endif // !LOG_DISABLED
// Initialize our platform strategies first before invoking the rest
// of the initialization code which may depend on the strategies.
WebPlatformStrategies::initializeIfNecessary();
#if ENABLE(SQL_DATABASE)
[WebDatabaseManager sharedWebDatabaseManager];
#endif
WebKitInitializeStorageIfNecessary();
WebKitInitializeApplicationCachePathIfNecessary();
Settings::setDefaultMinDOMTimerInterval(0.004);
Settings::setShouldRespectPriorityInCSSAttributeSetters(shouldRespectPriorityInCSSAttributeSetters());
didOneTimeInitialization = true;
}
Page::PageClients pageClients;
pageClients.chromeClient = new WebChromeClient(self);
pageClients.contextMenuClient = new WebContextMenuClient(self);
pageClients.editorClient = new WebEditorClient(self);
#if ENABLE(DRAG_SUPPORT)
pageClients.dragClient = new WebDragClient(self);
#endif
pageClients.inspectorClient = new WebInspectorClient(self);
pageClients.alternativeTextClient = new WebAlternativeTextClient(self);
_private->page = new Page(pageClients);
#if ENABLE(GEOLOCATION)
WebCore::provideGeolocationTo(_private->page, new WebGeolocationClient(self));
#endif
#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
WebCore::provideNotification(_private->page, new WebNotificationClient(self));
#endif
#if ENABLE(DEVICE_ORIENTATION)
WebCore::provideDeviceOrientationTo(_private->page, new WebDeviceOrientationClient(self));
#endif
_private->page->setCanStartMedia([self window]);
_private->page->settings()->setLocalStorageDatabasePath([[self preferences] _localStorageDatabasePath]);
_private->page->settings()->setUseLegacyBackgroundSizeShorthandBehavior(shouldUseLegacyBackgroundSizeShorthandBehavior());
if (needsOutlookQuirksScript()) {
_private->page->settings()->setShouldInjectUserScriptsInInitialEmptyDocument(true);
[self _injectOutlookQuirksScript];
}
if ([[NSUserDefaults standardUserDefaults] objectForKey:WebSmartInsertDeleteEnabled])
[self setSmartInsertDeleteEnabled:[[NSUserDefaults standardUserDefaults] boolForKey:WebSmartInsertDeleteEnabled]];
[WebFrame _createMainFrameWithPage:_private->page frameName:frameName frameView:frameView];
NSRunLoop *runLoop = [NSRunLoop mainRunLoop];
if (WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_LOADING_DURING_COMMON_RUNLOOP_MODES))
[self scheduleInRunLoop:runLoop forMode:(NSString *)kCFRunLoopCommonModes];
else
[self scheduleInRunLoop:runLoop forMode:NSDefaultRunLoopMode];
[self _addToAllWebViewsSet];
[self setGroupName:groupName];
// If there's already a next key view (e.g., from a nib), wire it up to our
// contained frame view. In any case, wire our next key view up to the our
// contained frame view. This works together with our becomeFirstResponder
// and setNextKeyView overrides.
NSView *nextKeyView = [self nextKeyView];
if (nextKeyView && nextKeyView != frameView)
[frameView setNextKeyView:nextKeyView];
[super setNextKeyView:frameView];
if ([[self class] shouldIncludeInWebKitStatistics])
++WebViewCount;
[self _registerDraggedTypes];
[self _setVisibilityState:([self _isViewVisible] ? WebPageVisibilityStateVisible : WebPageVisibilityStateHidden) isInitialState:YES];
WebPreferences *prefs = [self preferences];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:)
name:WebPreferencesChangedInternalNotification object:prefs];
[self _preferencesChanged:[self preferences]];
[[self preferences] _postPreferencesChangedAPINotification];
memoryPressureHandler().install();
if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_LOCAL_RESOURCE_SECURITY_RESTRICTION)) {
// Originally, we allowed all local loads.
SecurityPolicy::setLocalLoadPolicy(SecurityPolicy::AllowLocalLoadsForAll);
} else if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_MORE_STRICT_LOCAL_RESOURCE_SECURITY_RESTRICTION)) {
// Later, we allowed local loads for local URLs and documents loaded
// with substitute data.
SecurityPolicy::setLocalLoadPolicy(SecurityPolicy::AllowLocalLoadsForLocalAndSubstituteData);
}
if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_CONTENT_SNIFFING_FOR_FILE_URLS))
ResourceHandle::forceContentSniffing();
#if USE(GLIB)
[self _scheduleGlibContextIterations];
#endif
}
- (id)_initWithFrame:(NSRect)f frameName:(NSString *)frameName groupName:(NSString *)groupName usesDocumentViews:(BOOL)usesDocumentViews
{
// FIXME: Remove the usesDocumentViews parameter; it's only here for compatibility with WebKit nightly builds
// running against Safari 5 on Leopard.
ASSERT(usesDocumentViews);
self = [super initWithFrame:f];
if (!self)
return nil;
#ifdef ENABLE_WEBKIT_UNSET_DYLD_FRAMEWORK_PATH
// DYLD_FRAMEWORK_PATH is used so Safari will load the development version of WebKit, which
// may not work with other WebKit applications. Unsetting DYLD_FRAMEWORK_PATH removes the
// need for Safari to unset it to prevent it from being passed to applications it launches.
// Unsetting it when a WebView is first created is as good a place as any.
// See <http://bugs.webkit.org/show_bug.cgi?id=4286> for more details.
if (getenv("WEBKIT_UNSET_DYLD_FRAMEWORK_PATH")) {
unsetenv("DYLD_FRAMEWORK_PATH");
unsetenv("WEBKIT_UNSET_DYLD_FRAMEWORK_PATH");
}
#endif
_private = [[WebViewPrivate alloc] init];
[self _commonInitializationWithFrameName:frameName groupName:groupName];
[self setMaintainsBackForwardList: YES];
_private->page->setDeviceScaleFactor([self _deviceScaleFactor]);
return self;
}
- (void)_viewWillDrawInternal
{
Frame* frame = [self _mainCoreFrame];
if (frame && frame->view())
frame->view()->updateLayoutAndStyleIfNeededRecursive();
}
+ (NSArray *)_supportedMIMETypes
{
// Load the plug-in DB allowing plug-ins to install types.
[WebPluginDatabase sharedDatabase];
return [[WebFrameView _viewTypesAllowImageTypeOmission:NO] allKeys];
}
+ (NSArray *)_supportedFileExtensions
{
NSMutableSet *extensions = [[NSMutableSet alloc] init];
NSArray *MIMETypes = [self _supportedMIMETypes];
NSEnumerator *enumerator = [MIMETypes objectEnumerator];
NSString *MIMEType;
while ((MIMEType = [enumerator nextObject]) != nil) {
NSArray *extensionsForType = WKGetExtensionsForMIMEType(MIMEType);
if (extensionsForType) {
[extensions addObjectsFromArray:extensionsForType];
}
}
NSArray *uniqueExtensions = [extensions allObjects];
[extensions release];
return uniqueExtensions;
}
static NSMutableSet *knownPluginMIMETypes()
{
static NSMutableSet *mimeTypes = [[NSMutableSet alloc] init];
return mimeTypes;
}
+ (void)_registerPluginMIMEType:(NSString *)MIMEType
{
[WebView registerViewClass:[WebHTMLView class] representationClass:[WebHTMLRepresentation class] forMIMEType:MIMEType];
[knownPluginMIMETypes() addObject:MIMEType];
}
+ (void)_unregisterPluginMIMEType:(NSString *)MIMEType
{
[self _unregisterViewClassAndRepresentationClassForMIMEType:MIMEType];
[knownPluginMIMETypes() removeObject:MIMEType];
}
+ (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType allowingPlugins:(BOOL)allowPlugins
{
MIMEType = [MIMEType lowercaseString];
Class viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:YES] _webkit_objectForMIMEType:MIMEType];
Class repClass = [[WebDataSource _repTypesAllowImageTypeOmission:YES] _webkit_objectForMIMEType:MIMEType];
if (!viewClass || !repClass || [[WebPDFView supportedMIMETypes] containsObject:MIMEType]) {
// Our optimization to avoid loading the plug-in DB and image types for the HTML case failed.
if (allowPlugins) {
// Load the plug-in DB allowing plug-ins to install types.
[WebPluginDatabase sharedDatabase];
}
// Load the image types and get the view class and rep class. This should be the fullest picture of all handled types.
viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:NO] _webkit_objectForMIMEType:MIMEType];
repClass = [[WebDataSource _repTypesAllowImageTypeOmission:NO] _webkit_objectForMIMEType:MIMEType];
}
if (viewClass && repClass) {
if (viewClass == [WebHTMLView class] && repClass == [WebHTMLRepresentation class]) {
// Special-case WebHTMLView for text types that shouldn't be shown.
if ([[WebHTMLView unsupportedTextMIMETypes] containsObject:MIMEType])
return NO;
// If the MIME type is a known plug-in we might not want to load it.
if (!allowPlugins && [knownPluginMIMETypes() containsObject:MIMEType]) {
BOOL isSupportedByWebKit = [[WebHTMLView supportedNonImageMIMETypes] containsObject:MIMEType] ||
[[WebHTMLView supportedMIMETypes] containsObject:MIMEType];
// If this is a known plug-in MIME type and WebKit can't show it natively, we don't want to show it.
if (!isSupportedByWebKit)
return NO;
}
}
if (vClass)
*vClass = viewClass;
if (rClass)
*rClass = repClass;
return YES;
}
return NO;
}
- (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType
{
if ([[self class] _viewClass:vClass andRepresentationClass:rClass forMIMEType:MIMEType allowingPlugins:[_private->preferences arePlugInsEnabled]])
return YES;
if (_private->pluginDatabase) {
WebBasePluginPackage *pluginPackage = [_private->pluginDatabase pluginForMIMEType:MIMEType];
if (pluginPackage) {
if (vClass)
*vClass = [WebHTMLView class];
if (rClass)
*rClass = [WebHTMLRepresentation class];
return YES;
}
}
return NO;
}
+ (void)_setAlwaysUseATSU:(BOOL)f
{
[self _setAlwaysUsesComplexTextCodePath:f];
}
+ (void)_setAlwaysUsesComplexTextCodePath:(BOOL)f
{
Font::setCodePath(f ? Font::Complex : Font::Auto);
}
+ (void)_setAllowsRoundingHacks:(BOOL)allowsRoundingHacks
{
TextRun::setAllowsRoundingHacks(allowsRoundingHacks);
}
+ (BOOL)_allowsRoundingHacks
{
return TextRun::allowsRoundingHacks();
}
+ (BOOL)canCloseAllWebViews
{
return DOMWindow::dispatchAllPendingBeforeUnloadEvents();
}
+ (void)closeAllWebViews
{
DOMWindow::dispatchAllPendingUnloadEvents();
// This will close the WebViews in a random order. Change this if close order is important.
// Make a new set to avoid mutating the set we are enumerating.
NSSet *webViewsToClose = [NSSet setWithSet:(NSSet *)allWebViewsSet];
NSEnumerator *enumerator = [webViewsToClose objectEnumerator];
while (WebView *webView = [enumerator nextObject])
[webView close];
}
+ (BOOL)canShowFile:(NSString *)path
{
return [[self class] canShowMIMEType:[WebView _MIMETypeForFile:path]];
}
+ (NSString *)suggestedFileExtensionForMIMEType:(NSString *)type
{
return WKGetPreferredExtensionForMIMEType(type);
}
- (BOOL)_isClosed
{
return !_private || _private->closed;
}
- (void)_closePluginDatabases
{
pluginDatabaseClientCount--;
// Close both sets of plug-in databases because plug-ins need an opportunity to clean up files, etc.
// Unload the WebView local plug-in database.
if (_private->pluginDatabase) {
[_private->pluginDatabase destroyAllPluginInstanceViews];
[_private->pluginDatabase close];
[_private->pluginDatabase release];
_private->pluginDatabase = nil;
}
// Keep the global plug-in database active until the app terminates to avoid having to reload plug-in bundles.
if (!pluginDatabaseClientCount && applicationIsTerminating)
[WebPluginDatabase closeSharedDatabase];
}
- (void)_closeWithFastTeardown
{
#ifndef NDEBUG
WTF::RefCountedLeakCounter::suppressMessages("At least one WebView was closed with fast teardown.");
#endif
[[NSDistributedNotificationCenter defaultCenter] removeObserver:self];
[[NSNotificationCenter defaultCenter] removeObserver:self];
[self _closePluginDatabases];
}
static bool fastDocumentTeardownEnabled()
{
#ifdef NDEBUG
static bool enabled = ![[NSUserDefaults standardUserDefaults] boolForKey:WebKitEnableFullDocumentTeardownPreferenceKey];
#else
static bool initialized = false;
static bool enabled = false;
if (!initialized) {
// This allows debug builds to default to not have fast teardown, so leak checking still works.
// But still allow the WebKitEnableFullDocumentTeardown default to override it if present.
NSNumber *setting = [[NSUserDefaults standardUserDefaults] objectForKey:WebKitEnableFullDocumentTeardownPreferenceKey];
if (setting)
enabled = ![setting boolValue];
initialized = true;
}
#endif
return enabled;
}
// _close is here only for backward compatibility; clients and subclasses should use
// public method -close instead.
- (void)_close
{
if (!_private || _private->closed)
return;
_private->closed = YES;
[self _removeFromAllWebViewsSet];
#ifndef NDEBUG
WTF::RefCountedLeakCounter::cancelMessageSuppression(webViewIsOpen);
#endif
// To quit the apps fast we skip document teardown, except plugins
// need to be destroyed and unloaded.
if (applicationIsTerminating && fastDocumentTeardownEnabled()) {
[self _closeWithFastTeardown];
return;
}
#if ENABLE(VIDEO)
[self _exitFullscreen];
#endif
if (Frame* mainFrame = [self _mainCoreFrame])
mainFrame->loader()->detachFromParent();
[self setHostWindow:nil];
[self setDownloadDelegate:nil];
[self setEditingDelegate:nil];
[self setFrameLoadDelegate:nil];
[self setPolicyDelegate:nil];
[self setResourceLoadDelegate:nil];
[self setScriptDebugDelegate:nil];
[self setUIDelegate:nil];
[_private->inspector webViewClosed];
// To avoid leaks, call removeDragCaret in case it wasn't called after moveDragCaretToPoint.
[self removeDragCaret];
// Deleteing the WebCore::Page will clear the page cache so we call destroy on
// all the plug-ins in the page cache to break any retain cycles.
// See comment in HistoryItem::releaseAllPendingPageCaches() for more information.
Page* page = _private->page;
_private->page = 0;
delete page;
if (_private->hasSpellCheckerDocumentTag) {
[[NSSpellChecker sharedSpellChecker] closeSpellDocumentWithTag:_private->spellCheckerDocumentTag];
_private->hasSpellCheckerDocumentTag = NO;
}
#if USE(ACCELERATED_COMPOSITING)
if (_private->layerFlushController) {
_private->layerFlushController->invalidateObserver();
_private->layerFlushController = nullptr;
}
#endif
#if USE(GLIB)
[self _clearGlibLoopObserver];
#endif
[[self _notificationProvider] unregisterWebView:self];
[[NSDistributedNotificationCenter defaultCenter] removeObserver:self];
[[NSNotificationCenter defaultCenter] removeObserver:self];
[WebPreferences _removeReferenceForIdentifier:[self preferencesIdentifier]];
WebPreferences *preferences = _private->preferences;
_private->preferences = nil;
[preferences didRemoveFromWebView];
[preferences release];
[self _closePluginDatabases];
#ifndef NDEBUG
// Need this to make leak messages accurate.
if (applicationIsTerminating) {
gcController().garbageCollectNow();
[WebCache setDisabled:YES];
}
#endif
}
// Indicates if the WebView is in the midst of a user gesture.
- (BOOL)_isProcessingUserGesture
{
return ScriptController::processingUserGesture();
}
+ (NSString *)_MIMETypeForFile:(NSString *)path
{
NSString *extension = [path pathExtension];
NSString *MIMEType = nil;
// Get the MIME type from the extension.
if ([extension length] != 0) {
MIMEType = WKGetMIMETypeForExtension(extension);
}
// If we can't get a known MIME type from the extension, sniff.
if ([MIMEType length] == 0 || [MIMEType isEqualToString:@"application/octet-stream"]) {
NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:path];
NSData *data = [handle readDataOfLength:WEB_GUESS_MIME_TYPE_PEEK_LENGTH];
[handle closeFile];
if ([data length] != 0) {
MIMEType = [data _webkit_guessedMIMEType];
}
if ([MIMEType length] == 0) {
MIMEType = @"application/octet-stream";
}
}
return MIMEType;
}
- (WebDownload *)_downloadURL:(NSURL *)URL
{
ASSERT(URL);
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:URL];
WebDownload *download = [WebDownload _downloadWithRequest:request
delegate:_private->downloadDelegate
directory:nil];
[request release];
return download;
}
- (WebView *)_openNewWindowWithRequest:(NSURLRequest *)request
{
NSDictionary *features = [[NSDictionary alloc] init];
WebView *newWindowWebView = [[self _UIDelegateForwarder] webView:self
createWebViewWithRequest:nil
windowFeatures:features];
[features release];
if (!newWindowWebView)
return nil;
CallUIDelegate(newWindowWebView, @selector(webViewShow:));
return newWindowWebView;
}
- (WebInspector *)inspector
{
if (!_private->inspector)
_private->inspector = [[WebInspector alloc] initWithWebView:self];
return _private->inspector;
}
- (WebCore::Page*)page
{
return _private->page;
}
- (NSMenu *)_menuForElement:(NSDictionary *)element defaultItems:(NSArray *)items
{
NSArray *defaultMenuItems = [[WebDefaultUIDelegate sharedUIDelegate] webView:self contextMenuItemsForElement:element defaultMenuItems:items];
NSArray *menuItems = defaultMenuItems;
// CallUIDelegate returns nil if UIDelegate is nil or doesn't respond to the selector. So we need to check that here
// to distinguish between using defaultMenuItems or the delegate really returning nil to say "no context menu".
SEL selector = @selector(webView:contextMenuItemsForElement:defaultMenuItems:);
if (_private->UIDelegate && [_private->UIDelegate respondsToSelector:selector]) {
menuItems = CallUIDelegate(self, selector, element, defaultMenuItems);
if (!menuItems)
return nil;
}
unsigned count = [menuItems count];
if (!count)
return nil;
NSMenu *menu = [[NSMenu alloc] init];
for (unsigned i = 0; i < count; i++)
[menu addItem:[menuItems objectAtIndex:i]];
return [menu autorelease];
}
- (void)_mouseDidMoveOverElement:(NSDictionary *)dictionary modifierFlags:(NSUInteger)modifierFlags
{
// We originally intended to call this delegate method sometimes with a nil dictionary, but due to
// a bug dating back to WebKit 1.0 this delegate was never called with nil! Unfortunately we can't
// start calling this with nil since it will break Adobe Help Viewer, and possibly other clients.
if (!dictionary)
return;
CallUIDelegate(self, @selector(webView:mouseDidMoveOverElement:modifierFlags:), dictionary, modifierFlags);
}
- (void)_loadBackForwardListFromOtherView:(WebView *)otherView
{
if (!_private->page)
return;
if (!otherView->_private->page)
return;
// It turns out the right combination of behavior is done with the back/forward load
// type. (See behavior matrix at the top of WebFramePrivate.) So we copy all the items
// in the back forward list, and go to the current one.
BackForwardList* backForwardList = _private->page->backForwardList();
ASSERT(!backForwardList->currentItem()); // destination list should be empty
BackForwardList* otherBackForwardList = otherView->_private->page->backForwardList();
if (!otherBackForwardList->currentItem())
return; // empty back forward list, bail
HistoryItem* newItemToGoTo = 0;
int lastItemIndex = otherBackForwardList->forwardListCount();
for (int i = -otherBackForwardList->backListCount(); i <= lastItemIndex; ++i) {
if (i == 0) {
// If this item is showing , save away its current scroll and form state,
// since that might have changed since loading and it is normally not saved
// until we leave that page.
otherView->_private->page->mainFrame()->loader()->history()->saveDocumentAndScrollState();
}
RefPtr<HistoryItem> newItem = otherBackForwardList->itemAtIndex(i)->copy();
if (i == 0)
newItemToGoTo = newItem.get();
backForwardList->addItem(newItem.release());
}
ASSERT(newItemToGoTo);
_private->page->goToItem(newItemToGoTo, FrameLoadTypeIndexedBackForward);
}
- (void)_setFormDelegate: (id<WebFormDelegate>)delegate
{
_private->formDelegate = delegate;
}
- (id<WebFormDelegate>)_formDelegate
{
return _private->formDelegate;
}
- (BOOL)_needsAdobeFrameReloadingQuirk
{
static BOOL needsQuirk = WKAppVersionCheckLessThan(@"com.adobe.Acrobat", -1, 9.0)
|| WKAppVersionCheckLessThan(@"com.adobe.Acrobat.Pro", -1, 9.0)
|| WKAppVersionCheckLessThan(@"com.adobe.Reader", -1, 9.0)
|| WKAppVersionCheckLessThan(@"com.adobe.distiller", -1, 9.0)
|| WKAppVersionCheckLessThan(@"com.adobe.Contribute", -1, 4.2)
|| WKAppVersionCheckLessThan(@"com.adobe.dreamweaver-9.0", -1, 9.1)
|| WKAppVersionCheckLessThan(@"com.macromedia.fireworks", -1, 9.1)
|| WKAppVersionCheckLessThan(@"com.adobe.InCopy", -1, 5.1)
|| WKAppVersionCheckLessThan(@"com.adobe.InDesign", -1, 5.1)
|| WKAppVersionCheckLessThan(@"com.adobe.Soundbooth", -1, 2);
return needsQuirk;
}
- (BOOL)_needsLinkElementTextCSSQuirk
{
static BOOL needsQuirk = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_LINK_ELEMENT_TEXT_CSS_QUIRK)
&& WKAppVersionCheckLessThan(@"com.e-frontier.shade10", -1, 10.6);
return needsQuirk;
}
- (BOOL)_needsIsLoadingInAPISenseQuirk
{
static BOOL needsQuirk = WKAppVersionCheckLessThan(@"com.apple.iAdProducer", -1, 2.1);
return needsQuirk;
}
- (BOOL)_needsKeyboardEventDisambiguationQuirks
{
static BOOL needsQuirks = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_IE_COMPATIBLE_KEYBOARD_EVENT_DISPATCH) && !applicationIsSafari();
return needsQuirks;
}
- (BOOL)_needsFrameLoadDelegateRetainQuirk
{
static BOOL needsQuirk = WKAppVersionCheckLessThan(@"com.equinux.iSale5", -1, 5.6);
return needsQuirk;
}
static bool needsDidFinishLoadOrderQuirk()
{
static bool needsQuirk = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_CORRECT_DID_FINISH_LOAD_ORDER) && applicationIsAppleMail();
return needsQuirk;
}
static bool needsSelfRetainWhileLoadingQuirk()
{
static bool needsQuirk = applicationIsAperture();
return needsQuirk;
}
- (BOOL)_needsPreHTML5ParserQuirks
{
// AOL Instant Messenger and Microsoft My Day contain markup incompatible
// with the new HTML5 parser. If these applications were linked against a
// version of WebKit prior to the introduction of the HTML5 parser, enable
// parser quirks to maintain compatibility. For details, see
// <https://bugs.webkit.org/show_bug.cgi?id=46134> and
// <https://bugs.webkit.org/show_bug.cgi?id=46334>.
static bool isApplicationNeedingParserQuirks = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_HTML5_PARSER)
&& (applicationIsAOLInstantMessenger() || applicationIsMicrosoftMyDay());
// Mail.app must continue to display HTML email that contains quirky markup.
static bool isAppleMail = applicationIsAppleMail();
return isApplicationNeedingParserQuirks
|| isAppleMail
#if ENABLE(DASHBOARD_SUPPORT)
// Pre-HTML5 parser quirks are required to remain compatible with many
// Dashboard widgets. See <rdar://problem/8175982>.
|| (_private->page && _private->page->settings()->usesDashboardBackwardCompatibilityMode())
#endif
|| [[self preferences] usePreHTML5ParserQuirks];
}
- (BOOL)_needsUnrestrictedGetMatchedCSSRules
{
static bool needsUnrestrictedGetMatchedCSSRules = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_GET_MATCHED_CSS_RULES_RESTRICTIONS) && applicationIsSafari();
return needsUnrestrictedGetMatchedCSSRules;
}
- (void)_preferencesChangedNotification:(NSNotification *)notification
{
WebPreferences *preferences = (WebPreferences *)[notification object];
[self _preferencesChanged:preferences];
}
- (void)_preferencesChanged:(WebPreferences *)preferences
{
ASSERT(preferences == [self preferences]);
if (!_private->userAgentOverridden)
_private->userAgent = String();
// Cache this value so we don't have to read NSUserDefaults on each page load
_private->useSiteSpecificSpoofing = [preferences _useSiteSpecificSpoofing];
// Update corresponding WebCore Settings object.
if (!_private->page)
return;
Settings* settings = _private->page->settings();
settings->setCursiveFontFamily([preferences cursiveFontFamily]);
settings->setDefaultFixedFontSize([preferences defaultFixedFontSize]);
settings->setDefaultFontSize([preferences defaultFontSize]);
settings->setDefaultTextEncodingName([preferences defaultTextEncodingName]);
settings->setUsesEncodingDetector([preferences usesEncodingDetector]);
settings->setFantasyFontFamily([preferences fantasyFontFamily]);
settings->setFixedFontFamily([preferences fixedFontFamily]);
settings->setScreenFontSubstitutionEnabled(
#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
[[NSUserDefaults standardUserDefaults] boolForKey:@"NSFontDefaultScreenFontSubstitutionEnabled"] ||
#endif
[preferences screenFontSubstitutionEnabled]
);
settings->setForceFTPDirectoryListings([preferences _forceFTPDirectoryListings]);
settings->setFTPDirectoryTemplatePath([preferences _ftpDirectoryTemplatePath]);
settings->setLocalStorageDatabasePath([preferences _localStorageDatabasePath]);
settings->setJavaEnabled([preferences isJavaEnabled]);
settings->setScriptEnabled([preferences isJavaScriptEnabled]);
settings->setWebSecurityEnabled([preferences isWebSecurityEnabled]);
settings->setAllowUniversalAccessFromFileURLs([preferences allowUniversalAccessFromFileURLs]);
settings->setAllowFileAccessFromFileURLs([preferences allowFileAccessFromFileURLs]);
settings->setJavaScriptCanOpenWindowsAutomatically([preferences javaScriptCanOpenWindowsAutomatically]);
settings->setMinimumFontSize([preferences minimumFontSize]);
settings->setMinimumLogicalFontSize([preferences minimumLogicalFontSize]);
settings->setPictographFontFamily([preferences pictographFontFamily]);
settings->setPluginsEnabled([preferences arePlugInsEnabled]);
#if ENABLE(SQL_DATABASE)
DatabaseManager::manager().setIsAvailable([preferences databasesEnabled]);
#endif
settings->setLocalStorageEnabled([preferences localStorageEnabled]);
settings->setExperimentalNotificationsEnabled([preferences experimentalNotificationsEnabled]);
bool privateBrowsingEnabled = [preferences privateBrowsingEnabled];
#if PLATFORM(MAC) || USE(CFNETWORK)
if (privateBrowsingEnabled)
WebFrameNetworkingContext::ensurePrivateBrowsingSession();
else
WebFrameNetworkingContext::destroyPrivateBrowsingSession();
#endif
settings->setPrivateBrowsingEnabled(privateBrowsingEnabled);
settings->setSansSerifFontFamily([preferences sansSerifFontFamily]);
settings->setSerifFontFamily([preferences serifFontFamily]);
settings->setStandardFontFamily([preferences standardFontFamily]);
settings->setLoadsImagesAutomatically([preferences loadsImagesAutomatically]);
settings->setLoadsSiteIconsIgnoringImageLoadingSetting([preferences loadsSiteIconsIgnoringImageLoadingPreference]);
settings->setShouldPrintBackgrounds([preferences shouldPrintBackgrounds]);
settings->setTextAreasAreResizable([preferences textAreasAreResizable]);
settings->setShrinksStandaloneImagesToFit([preferences shrinksStandaloneImagesToFit]);
settings->setEditableLinkBehavior(core([preferences editableLinkBehavior]));
settings->setTextDirectionSubmenuInclusionBehavior(core([preferences textDirectionSubmenuInclusionBehavior]));
settings->setDOMPasteAllowed([preferences isDOMPasteAllowed]);
settings->setUsesPageCache([self usesPageCache]);
settings->setPageCacheSupportsPlugins([preferences pageCacheSupportsPlugins]);
settings->setBackForwardCacheExpirationInterval([preferences _backForwardCacheExpirationInterval]);
settings->setShowsURLsInToolTips([preferences showsURLsInToolTips]);
settings->setShowsToolTipOverTruncatedText([preferences showsToolTipOverTruncatedText]);
settings->setDeveloperExtrasEnabled([preferences developerExtrasEnabled]);
settings->setJavaScriptExperimentsEnabled([preferences javaScriptExperimentsEnabled]);
settings->setAuthorAndUserStylesEnabled([preferences authorAndUserStylesEnabled]);
settings->setApplicationChromeMode([preferences applicationChromeModeEnabled]);
if ([preferences userStyleSheetEnabled]) {
NSString* location = [[preferences userStyleSheetLocation] _web_originalDataAsString];
if ([location isEqualToString:@"apple-dashboard://stylesheet"])
location = @"file:///System/Library/PrivateFrameworks/DashboardClient.framework/Resources/widget.css";
settings->setUserStyleSheetLocation([NSURL URLWithString:(location ? location : @"")]);
} else
settings->setUserStyleSheetLocation([NSURL URLWithString:@""]);
settings->setNeedsAdobeFrameReloadingQuirk([self _needsAdobeFrameReloadingQuirk]);
settings->setTreatsAnyTextCSSLinkAsStylesheet([self _needsLinkElementTextCSSQuirk]);
settings->setNeedsKeyboardEventDisambiguationQuirks([self _needsKeyboardEventDisambiguationQuirks]);
settings->setNeedsSiteSpecificQuirks(_private->useSiteSpecificSpoofing);
settings->setWebArchiveDebugModeEnabled([preferences webArchiveDebugModeEnabled]);
settings->setLocalFileContentSniffingEnabled([preferences localFileContentSniffingEnabled]);
settings->setOfflineWebApplicationCacheEnabled([preferences offlineWebApplicationCacheEnabled]);
settings->setJavaScriptCanAccessClipboard([preferences javaScriptCanAccessClipboard]);
settings->setXSSAuditorEnabled([preferences isXSSAuditorEnabled]);
settings->setEnforceCSSMIMETypeInNoQuirksMode(!WKAppVersionCheckLessThan(@"com.apple.iWeb", -1, 2.1));
settings->setDNSPrefetchingEnabled([preferences isDNSPrefetchingEnabled]);
// FIXME: Enabling accelerated compositing when WebGL is enabled causes tests to fail on Leopard which expect HW compositing to be disabled.
// Until we fix that, I will comment out the test (CFM)
settings->setAcceleratedCompositingEnabled([preferences acceleratedCompositingEnabled]);
settings->setAcceleratedDrawingEnabled([preferences acceleratedDrawingEnabled]);
settings->setCanvasUsesAcceleratedDrawing([preferences canvasUsesAcceleratedDrawing]);
settings->setShowDebugBorders([preferences showDebugBorders]);
settings->setShowRepaintCounter([preferences showRepaintCounter]);
settings->setWebAudioEnabled([preferences webAudioEnabled]);
settings->setWebGLEnabled([preferences webGLEnabled]);
settings->setAccelerated2dCanvasEnabled([preferences accelerated2dCanvasEnabled]);
settings->setLoadDeferringEnabled(shouldEnableLoadDeferring());
settings->setFrameFlatteningEnabled([preferences isFrameFlatteningEnabled]);
settings->setSpatialNavigationEnabled([preferences isSpatialNavigationEnabled]);
settings->setPaginateDuringLayoutEnabled([preferences paginateDuringLayoutEnabled]);
#if ENABLE(CSS_SHADERS)
settings->setCSSCustomFilterEnabled([preferences cssCustomFilterEnabled]);
#endif
RuntimeEnabledFeatures::setCSSRegionsEnabled([preferences cssRegionsEnabled]);
RuntimeEnabledFeatures::setCSSCompositingEnabled([preferences cssCompositingEnabled]);
#if ENABLE(IFRAME_SEAMLESS)
RuntimeEnabledFeatures::setSeamlessIFramesEnabled([preferences seamlessIFramesEnabled]);
#endif
settings->setCSSGridLayoutEnabled([preferences cssGridLayoutEnabled]);
#if ENABLE(FULLSCREEN_API)
settings->setFullScreenEnabled([preferences fullScreenEnabled]);
#endif
settings->setAsynchronousSpellCheckingEnabled([preferences asynchronousSpellCheckingEnabled]);
settings->setMemoryInfoEnabled([preferences memoryInfoEnabled]);
settings->setHyperlinkAuditingEnabled([preferences hyperlinkAuditingEnabled]);
settings->setUsePreHTML5ParserQuirks([self _needsPreHTML5ParserQuirks]);
settings->setCrossOriginCheckInGetMatchedCSSRulesDisabled([self _needsUnrestrictedGetMatchedCSSRules]);
settings->setInteractiveFormValidationEnabled([self interactiveFormValidationEnabled]);
settings->setValidationMessageTimerMagnification([self validationMessageTimerMagnification]);
#if USE(AVFOUNDATION)
#if ENABLE(FULLSCREEN_API)
settings->setAVFoundationEnabled([preferences isAVFoundationEnabled] && [preferences fullScreenEnabled]);
#else
settings->setAVFoundationEnabled(false);
#endif
#endif
#if PLATFORM(MAC) || (PLATFORM(QT) && USE(QTKIT))
settings->setQTKitEnabled([preferences isQTKitEnabled]);
#endif
settings->setMediaPlaybackRequiresUserGesture([preferences mediaPlaybackRequiresUserGesture]);
settings->setMediaPlaybackAllowsInline([preferences mediaPlaybackAllowsInline]);
settings->setSuppressesIncrementalRendering([preferences suppressesIncrementalRendering]);
settings->setRegionBasedColumnsEnabled([preferences regionBasedColumnsEnabled]);
settings->setBackspaceKeyNavigationEnabled([preferences backspaceKeyNavigationEnabled]);
settings->setWantsBalancedSetDefersLoadingBehavior([preferences wantsBalancedSetDefersLoadingBehavior]);
settings->setMockScrollbarsEnabled([preferences mockScrollbarsEnabled]);
#if ENABLE(VIDEO_TRACK)
settings->setShouldDisplaySubtitles([preferences shouldDisplaySubtitles]);
settings->setShouldDisplayCaptions([preferences shouldDisplayCaptions]);
settings->setShouldDisplayTextDescriptions([preferences shouldDisplayTextDescriptions]);
#endif
settings->setShouldRespectImageOrientation([preferences shouldRespectImageOrientation]);
settings->setNeedsIsLoadingInAPISenseQuirk([self _needsIsLoadingInAPISenseQuirk]);
settings->setRequestAnimationFrameEnabled([preferences requestAnimationFrameEnabled]);
settings->setNeedsDidFinishLoadOrderQuirk(needsDidFinishLoadOrderQuirk());
settings->setDiagnosticLoggingEnabled([preferences diagnosticLoggingEnabled]);
switch ([preferences storageBlockingPolicy]) {
case WebAllowAllStorage:
settings->setStorageBlockingPolicy(SecurityOrigin::AllowAllStorage);
break;
case WebBlockThirdPartyStorage:
settings->setStorageBlockingPolicy(SecurityOrigin::BlockThirdPartyStorage);
break;
case WebBlockAllStorage:
settings->setStorageBlockingPolicy(SecurityOrigin::BlockAllStorage);
break;
}
settings->setPlugInSnapshottingEnabled([preferences plugInSnapshottingEnabled]);
#if ENABLE(HIDDEN_PAGE_DOM_TIMER_THROTTLING)
settings->setHiddenPageDOMTimerThrottlingEnabled([preferences hiddenPageDOMTimerThrottlingEnabled]);
#endif
#if ENABLE(PAGE_VISIBILITY_API)
settings->setHiddenPageCSSAnimationSuspensionEnabled([preferences hiddenPageCSSAnimationSuspensionEnabled]);
#endif
// We have enabled this setting in WebKit2 for the sake of some ScrollingCoordinator work.
// To avoid possible rendering differences, we should enable it for WebKit1 too.
settings->setFixedPositionCreatesStackingContext(true);
NSTimeInterval timeout = [preferences incrementalRenderingSuppressionTimeoutInSeconds];
if (timeout > 0)
settings->setIncrementalRenderingSuppressionTimeoutInSeconds(timeout);
// Application Cache Preferences are stored on the global cache storage manager, not in Settings.
[WebApplicationCache setDefaultOriginQuota:[preferences applicationCacheDefaultOriginQuota]];
BOOL zoomsTextOnly = [preferences zoomsTextOnly];
if (_private->zoomsTextOnly != zoomsTextOnly)
[self _setZoomMultiplier:_private->zoomMultiplier isTextOnly:zoomsTextOnly];
}
static inline IMP getMethod(id o, SEL s)
{
return [o respondsToSelector:s] ? [o methodForSelector:s] : 0;
}
- (void)_cacheResourceLoadDelegateImplementations
{
WebResourceDelegateImplementationCache *cache = &_private->resourceLoadDelegateImplementations;
id delegate = _private->resourceProgressDelegate;
if (!delegate) {
bzero(cache, sizeof(WebResourceDelegateImplementationCache));
return;
}
cache->didCancelAuthenticationChallengeFunc = getMethod(delegate, @selector(webView:resource:didCancelAuthenticationChallenge:fromDataSource:));
cache->didFailLoadingWithErrorFromDataSourceFunc = getMethod(delegate, @selector(webView:resource:didFailLoadingWithError:fromDataSource:));
cache->didFinishLoadingFromDataSourceFunc = getMethod(delegate, @selector(webView:resource:didFinishLoadingFromDataSource:));
cache->didLoadResourceFromMemoryCacheFunc = getMethod(delegate, @selector(webView:didLoadResourceFromMemoryCache:response:length:fromDataSource:));
cache->didReceiveAuthenticationChallengeFunc = getMethod(delegate, @selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:));
#if USE(PROTECTION_SPACE_AUTH_CALLBACK)
cache->canAuthenticateAgainstProtectionSpaceFunc = getMethod(delegate, @selector(webView:resource:canAuthenticateAgainstProtectionSpace:forDataSource:));
#endif
cache->didReceiveContentLengthFunc = getMethod(delegate, @selector(webView:resource:didReceiveContentLength:fromDataSource:));
cache->didReceiveResponseFunc = getMethod(delegate, @selector(webView:resource:didReceiveResponse:fromDataSource:));
cache->identifierForRequestFunc = getMethod(delegate, @selector(webView:identifierForInitialRequest:fromDataSource:));
cache->plugInFailedWithErrorFunc = getMethod(delegate, @selector(webView:plugInFailedWithError:dataSource:));
cache->willCacheResponseFunc = getMethod(delegate, @selector(webView:resource:willCacheResponse:fromDataSource:));
cache->willSendRequestFunc = getMethod(delegate, @selector(webView:resource:willSendRequest:redirectResponse:fromDataSource:));
cache->shouldUseCredentialStorageFunc = getMethod(delegate, @selector(webView:resource:shouldUseCredentialStorageForDataSource:));
cache->shouldPaintBrokenImageForURLFunc = getMethod(delegate, @selector(webView:shouldPaintBrokenImageForURL:));
}
- (void)_cacheFrameLoadDelegateImplementations
{
WebFrameLoadDelegateImplementationCache *cache = &_private->frameLoadDelegateImplementations;
id delegate = _private->frameLoadDelegate;
if (!delegate) {
bzero(cache, sizeof(WebFrameLoadDelegateImplementationCache));
return;
}
cache->didCancelClientRedirectForFrameFunc = getMethod(delegate, @selector(webView:didCancelClientRedirectForFrame:));
cache->didChangeLocationWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didChangeLocationWithinPageForFrame:));
cache->didPushStateWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didPushStateWithinPageForFrame:));
cache->didReplaceStateWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didReplaceStateWithinPageForFrame:));
cache->didPopStateWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didPopStateWithinPageForFrame:));
#if JSC_OBJC_API_ENABLED
cache->didCreateJavaScriptContextForFrameFunc = getMethod(delegate, @selector(webView:didCreateJavaScriptContext:forFrame:));
#endif
cache->didClearWindowObjectForFrameFunc = getMethod(delegate, @selector(webView:didClearWindowObject:forFrame:));
cache->didClearWindowObjectForFrameInScriptWorldFunc = getMethod(delegate, @selector(webView:didClearWindowObjectForFrame:inScriptWorld:));
cache->didClearInspectorWindowObjectForFrameFunc = getMethod(delegate, @selector(webView:didClearInspectorWindowObject:forFrame:));
cache->didCommitLoadForFrameFunc = getMethod(delegate, @selector(webView:didCommitLoadForFrame:));
cache->didFailLoadWithErrorForFrameFunc = getMethod(delegate, @selector(webView:didFailLoadWithError:forFrame:));
cache->didFailProvisionalLoadWithErrorForFrameFunc = getMethod(delegate, @selector(webView:didFailProvisionalLoadWithError:forFrame:));
cache->didFinishDocumentLoadForFrameFunc = getMethod(delegate, @selector(webView:didFinishDocumentLoadForFrame:));
cache->didFinishLoadForFrameFunc = getMethod(delegate, @selector(webView:didFinishLoadForFrame:));
cache->didFirstLayoutInFrameFunc = getMethod(delegate, @selector(webView:didFirstLayoutInFrame:));
cache->didFirstVisuallyNonEmptyLayoutInFrameFunc = getMethod(delegate, @selector(webView:didFirstVisuallyNonEmptyLayoutInFrame:));
cache->didLayoutFunc = getMethod(delegate, @selector(webView:didLayout:));
cache->didHandleOnloadEventsForFrameFunc = getMethod(delegate, @selector(webView:didHandleOnloadEventsForFrame:));
cache->didReceiveIconForFrameFunc = getMethod(delegate, @selector(webView:didReceiveIcon:forFrame:));
cache->didReceiveServerRedirectForProvisionalLoadForFrameFunc = getMethod(delegate, @selector(webView:didReceiveServerRedirectForProvisionalLoadForFrame:));
cache->didReceiveTitleForFrameFunc = getMethod(delegate, @selector(webView:didReceiveTitle:forFrame:));
cache->didStartProvisionalLoadForFrameFunc = getMethod(delegate, @selector(webView:didStartProvisionalLoadForFrame:));
cache->willCloseFrameFunc = getMethod(delegate, @selector(webView:willCloseFrame:));
cache->willPerformClientRedirectToURLDelayFireDateForFrameFunc = getMethod(delegate, @selector(webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:));
cache->windowScriptObjectAvailableFunc = getMethod(delegate, @selector(webView:windowScriptObjectAvailable:));
cache->didDisplayInsecureContentFunc = getMethod(delegate, @selector(webViewDidDisplayInsecureContent:));
cache->didRunInsecureContentFunc = getMethod(delegate, @selector(webView:didRunInsecureContent:));
cache->didDetectXSSFunc = getMethod(delegate, @selector(webView:didDetectXSS:));
cache->didRemoveFrameFromHierarchyFunc = getMethod(delegate, @selector(webView:didRemoveFrameFromHierarchy:));
// It would be nice to get rid of this code and transition all clients to using didLayout instead of
// didFirstLayoutInFrame and didFirstVisuallyNonEmptyLayoutInFrame. In the meantime, this is required
// for backwards compatibility.
Page* page = core(self);
if (page) {
unsigned milestones = DidFirstLayout;
if (cache->didFirstVisuallyNonEmptyLayoutInFrameFunc)
milestones |= DidFirstVisuallyNonEmptyLayout;
page->addLayoutMilestones(static_cast<LayoutMilestones>(milestones));
}
}
- (void)_cacheScriptDebugDelegateImplementations
{
WebScriptDebugDelegateImplementationCache *cache = &_private->scriptDebugDelegateImplementations;
id delegate = _private->scriptDebugDelegate;
if (!delegate) {
bzero(cache, sizeof(WebScriptDebugDelegateImplementationCache));
return;
}
cache->didParseSourceFunc = getMethod(delegate, @selector(webView:didParseSource:baseLineNumber:fromURL:sourceId:forWebFrame:));
if (cache->didParseSourceFunc)
cache->didParseSourceExpectsBaseLineNumber = YES;
else {
cache->didParseSourceExpectsBaseLineNumber = NO;
cache->didParseSourceFunc = getMethod(delegate, @selector(webView:didParseSource:fromURL:sourceId:forWebFrame:));
}
cache->failedToParseSourceFunc = getMethod(delegate, @selector(webView:failedToParseSource:baseLineNumber:fromURL:withError:forWebFrame:));
cache->didEnterCallFrameFunc = getMethod(delegate, @selector(webView:didEnterCallFrame:sourceId:line:forWebFrame:));
cache->willExecuteStatementFunc = getMethod(delegate, @selector(webView:willExecuteStatement:sourceId:line:forWebFrame:));
cache->willLeaveCallFrameFunc = getMethod(delegate, @selector(webView:willLeaveCallFrame:sourceId:line:forWebFrame:));
cache->exceptionWasRaisedFunc = getMethod(delegate, @selector(webView:exceptionWasRaised:hasHandler:sourceId:line:forWebFrame:));
if (cache->exceptionWasRaisedFunc)
cache->exceptionWasRaisedExpectsHasHandlerFlag = YES;
else {
cache->exceptionWasRaisedExpectsHasHandlerFlag = NO;
cache->exceptionWasRaisedFunc = getMethod(delegate, @selector(webView:exceptionWasRaised:sourceId:line:forWebFrame:));
}
}
- (void)_cacheHistoryDelegateImplementations
{
WebHistoryDelegateImplementationCache *cache = &_private->historyDelegateImplementations;
id delegate = _private->historyDelegate;
if (!delegate) {
bzero(cache, sizeof(WebHistoryDelegateImplementationCache));
return;
}
cache->navigatedFunc = getMethod(delegate, @selector(webView:didNavigateWithNavigationData:inFrame:));
cache->clientRedirectFunc = getMethod(delegate, @selector(webView:didPerformClientRedirectFromURL:toURL:inFrame:));
cache->serverRedirectFunc = getMethod(delegate, @selector(webView:didPerformServerRedirectFromURL:toURL:inFrame:));
cache->setTitleFunc = getMethod(delegate, @selector(webView:updateHistoryTitle:forURL:));
cache->populateVisitedLinksFunc = getMethod(delegate, @selector(populateVisitedLinksForWebView:));
}
- (id)_policyDelegateForwarder
{
if (!_private->policyDelegateForwarder)
_private->policyDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->policyDelegate defaultTarget:[WebDefaultPolicyDelegate sharedPolicyDelegate]];
return _private->policyDelegateForwarder;
}
- (id)_UIDelegateForwarder
{
if (!_private->UIDelegateForwarder)
_private->UIDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->UIDelegate defaultTarget:[WebDefaultUIDelegate sharedUIDelegate]];
return _private->UIDelegateForwarder;
}
- (id)_editingDelegateForwarder
{
// This can be called during window deallocation by QTMovieView in the QuickTime Cocoa Plug-in.
// Not sure if that is a bug or not.
if (!_private)
return nil;
if (!_private->editingDelegateForwarder)
_private->editingDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->editingDelegate defaultTarget:[WebDefaultEditingDelegate sharedEditingDelegate]];
return _private->editingDelegateForwarder;
}
- (void)_closeWindow
{
[[self _UIDelegateForwarder] webViewClose:self];
}
+ (void)_unregisterViewClassAndRepresentationClassForMIMEType:(NSString *)MIMEType
{
[[WebFrameView _viewTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType];
[[WebDataSource _repTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType];
// FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
// in the WebCore MIMEType registry. For now we're doing this in a safe, limited manner
// to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
MIMETypeRegistry::getSupportedNonImageMIMETypes().remove(MIMEType);
}
+ (void)_registerViewClass:(Class)viewClass representationClass:(Class)representationClass forURLScheme:(NSString *)URLScheme
{
NSString *MIMEType = [self _generatedMIMETypeForURLScheme:URLScheme];
[self registerViewClass:viewClass representationClass:representationClass forMIMEType:MIMEType];
// FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
// in the WebCore MIMEType registry. For now we're doing this in a safe, limited manner
// to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
if ([viewClass class] == [WebHTMLView class])
MIMETypeRegistry::getSupportedNonImageMIMETypes().add(MIMEType);
// This is used to make _representationExistsForURLScheme faster.
// Without this set, we'd have to create the MIME type each time.
if (schemesWithRepresentationsSet == nil) {
schemesWithRepresentationsSet = [[NSMutableSet alloc] init];
}
[schemesWithRepresentationsSet addObject:[[[URLScheme lowercaseString] copy] autorelease]];
}
+ (NSString *)_generatedMIMETypeForURLScheme:(NSString *)URLScheme
{
return [@"x-apple-web-kit/" stringByAppendingString:[URLScheme lowercaseString]];
}
+ (BOOL)_representationExistsForURLScheme:(NSString *)URLScheme
{
return [schemesWithRepresentationsSet containsObject:[URLScheme lowercaseString]];
}
+ (BOOL)_canHandleRequest:(NSURLRequest *)request forMainFrame:(BOOL)forMainFrame
{
// FIXME: If <rdar://problem/5217309> gets fixed, this check can be removed.
if (!request)
return NO;
if ([NSURLConnection canHandleRequest:request])
return YES;
NSString *scheme = [[request URL] scheme];
// Representations for URL schemes work at the top level.
if (forMainFrame && [self _representationExistsForURLScheme:scheme])
return YES;
if ([scheme _webkit_isCaseInsensitiveEqualToString:@"applewebdata"])
return YES;
#if ENABLE(BLOB)
if ([scheme _webkit_isCaseInsensitiveEqualToString:@"blob"])
return YES;
#endif
return NO;
}
+ (BOOL)_canHandleRequest:(NSURLRequest *)request
{
return [self _canHandleRequest:request forMainFrame:YES];
}
+ (NSString *)_decodeData:(NSData *)data
{
HTMLNames::init(); // this method is used for importing bookmarks at startup, so HTMLNames are likely to be uninitialized yet
RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("text/html"); // bookmark files are HTML
String result = decoder->decode(static_cast<const char*>([data bytes]), [data length]);
result.append(decoder->flush());
return result;
}
- (void)_pushPerformingProgrammaticFocus
{
_private->programmaticFocusCount++;
}
- (void)_popPerformingProgrammaticFocus
{
_private->programmaticFocusCount--;
}
- (BOOL)_isPerformingProgrammaticFocus
{
return _private->programmaticFocusCount != 0;
}
- (void)_didChangeValueForKey: (NSString *)key
{
LOG (Bindings, "calling didChangeValueForKey: %@", key);
[self didChangeValueForKey: key];
}
- (void)_willChangeValueForKey: (NSString *)key
{
LOG (Bindings, "calling willChangeValueForKey: %@", key);
[self willChangeValueForKey: key];
}
+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key {
static NSSet *manualNotifyKeys = nil;
if (!manualNotifyKeys)
manualNotifyKeys = [[NSSet alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey,
_WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, _WebMainFrameDocumentKey,
nil];
if ([manualNotifyKeys containsObject:key])
return NO;
return YES;
}
- (NSArray *)_declaredKeys {
static NSArray *declaredKeys = nil;
if (!declaredKeys)
declaredKeys = [[NSArray alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey,
_WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, _WebMainFrameDocumentKey, nil];
return declaredKeys;
}
- (void)setObservationInfo:(void *)info
{
_private->observationInfo = info;
}
- (void *)observationInfo
{
return _private->observationInfo;
}
- (void)_willChangeBackForwardKeys
{
[self _willChangeValueForKey: _WebCanGoBackKey];
[self _willChangeValueForKey: _WebCanGoForwardKey];
}
- (void)_didChangeBackForwardKeys
{
[self _didChangeValueForKey: _WebCanGoBackKey];
[self _didChangeValueForKey: _WebCanGoForwardKey];
}
- (void)_didStartProvisionalLoadForFrame:(WebFrame *)frame
{
if (needsSelfRetainWhileLoadingQuirk())
[self retain];
[self _willChangeBackForwardKeys];
if (frame == [self mainFrame]){
// Force an observer update by sending a will/did.
[self _willChangeValueForKey: _WebIsLoadingKey];
[self _didChangeValueForKey: _WebIsLoadingKey];
[self _willChangeValueForKey: _WebMainFrameURLKey];
}
[NSApp setWindowsNeedUpdate:YES];
#if ENABLE(FULLSCREEN_API)
Document* document = core([frame DOMDocument]);
if (Element* element = document ? document->webkitCurrentFullScreenElement() : 0) {
SEL selector = @selector(webView:closeFullScreenWithListener:);
if (_private->UIDelegate && [_private->UIDelegate respondsToSelector:selector]) {
WebKitFullScreenListener *listener = [[WebKitFullScreenListener alloc] initWithElement:element];
CallUIDelegate(self, selector, listener);
[listener release];
} else if (_private->newFullscreenController && [_private->newFullscreenController isFullScreen]) {
[_private->newFullscreenController close];
}
}
#endif
}
- (void)_didCommitLoadForFrame:(WebFrame *)frame
{
if (frame == [self mainFrame])
[self _didChangeValueForKey: _WebMainFrameURLKey];
[NSApp setWindowsNeedUpdate:YES];
}
- (void)_didFinishLoadForFrame:(WebFrame *)frame
{
if (needsSelfRetainWhileLoadingQuirk())
[self performSelector:@selector(release) withObject:nil afterDelay:0];
[self _didChangeBackForwardKeys];
if (frame == [self mainFrame]){
// Force an observer update by sending a will/did.
[self _willChangeValueForKey: _WebIsLoadingKey];
[self _didChangeValueForKey: _WebIsLoadingKey];
}
[NSApp setWindowsNeedUpdate:YES];
}
- (void)_didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
{
if (needsSelfRetainWhileLoadingQuirk())
[self performSelector:@selector(release) withObject:nil afterDelay:0];
[self _didChangeBackForwardKeys];
if (frame == [self mainFrame]){
// Force an observer update by sending a will/did.
[self _willChangeValueForKey: _WebIsLoadingKey];
[self _didChangeValueForKey: _WebIsLoadingKey];
}
[NSApp setWindowsNeedUpdate:YES];
}
- (void)_didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
{
if (needsSelfRetainWhileLoadingQuirk())
[self performSelector:@selector(release) withObject:nil afterDelay:0];
[self _didChangeBackForwardKeys];
if (frame == [self mainFrame]){
// Force an observer update by sending a will/did.
[self _willChangeValueForKey: _WebIsLoadingKey];
[self _didChangeValueForKey: _WebIsLoadingKey];
[self _didChangeValueForKey: _WebMainFrameURLKey];
}
[NSApp setWindowsNeedUpdate:YES];
}
- (NSCachedURLResponse *)_cachedResponseForURL:(NSURL *)URL
{
RetainPtr<NSMutableURLRequest *> request = adoptNS([[NSMutableURLRequest alloc] initWithURL:URL]);
[request _web_setHTTPUserAgent:[self userAgentForURL:URL]];
NSCachedURLResponse *cachedResponse;
if (!_private->page)
return nil;
if (CFURLStorageSessionRef storageSession = _private->page->mainFrame()->loader()->networkingContext()->storageSession().platformSession())
cachedResponse = WKCachedResponseForRequest(storageSession, request.get());
else
cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:request.get()];
return cachedResponse;
}
- (void)_writeImageForElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
{
NSURL *linkURL = [element objectForKey:WebElementLinkURLKey];
DOMElement *domElement = [element objectForKey:WebElementDOMNodeKey];
[pasteboard _web_writeImage:(NSImage *)(domElement ? nil : [element objectForKey:WebElementImageKey])
element:domElement
URL:linkURL ? linkURL : (NSURL *)[element objectForKey:WebElementImageURLKey]
title:[element objectForKey:WebElementImageAltStringKey]
archive:[[element objectForKey:WebElementDOMNodeKey] webArchive]
types:types
source:nil];
}
- (void)_writeLinkElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
{
[pasteboard _web_writeURL:[element objectForKey:WebElementLinkURLKey]
andTitle:[element objectForKey:WebElementLinkLabelKey]
types:types];
}
#if ENABLE(DRAG_SUPPORT)
- (void)_setInitiatedDrag:(BOOL)initiatedDrag
{
if (!_private->page)
return;
_private->page->dragController()->setDidInitiateDrag(initiatedDrag);
}
#endif
#if ENABLE(DASHBOARD_SUPPORT)
#define DASHBOARD_CONTROL_LABEL @"control"
- (void)_addControlRect:(NSRect)bounds clip:(NSRect)clip fromView:(NSView *)view toDashboardRegions:(NSMutableDictionary *)regions
{
NSRect adjustedBounds = bounds;
adjustedBounds.origin = [self convertPoint:bounds.origin fromView:view];
adjustedBounds.origin.y = [self bounds].size.height - adjustedBounds.origin.y;
adjustedBounds.size = bounds.size;
NSRect adjustedClip;
adjustedClip.origin = [self convertPoint:clip.origin fromView:view];
adjustedClip.origin.y = [self bounds].size.height - adjustedClip.origin.y;
adjustedClip.size = clip.size;
WebDashboardRegion *region = [[WebDashboardRegion alloc] initWithRect:adjustedBounds
clip:adjustedClip type:WebDashboardRegionTypeScrollerRectangle];
NSMutableArray *scrollerRegions = [regions objectForKey:DASHBOARD_CONTROL_LABEL];
if (!scrollerRegions) {
scrollerRegions = [[NSMutableArray alloc] init];
[regions setObject:scrollerRegions forKey:DASHBOARD_CONTROL_LABEL];
[scrollerRegions release];
}
[scrollerRegions addObject:region];
[region release];
}
- (void)_addScrollerDashboardRegionsForFrameView:(FrameView*)frameView dashboardRegions:(NSMutableDictionary *)regions
{
NSView *documentView = [[kit(frameView->frame()) frameView] documentView];
const HashSet<RefPtr<Widget> >* children = frameView->children();
HashSet<RefPtr<Widget> >::const_iterator end = children->end();
for (HashSet<RefPtr<Widget> >::const_iterator it = children->begin(); it != end; ++it) {
Widget* widget = (*it).get();
if (widget->isFrameView()) {
[self _addScrollerDashboardRegionsForFrameView:toFrameView(widget) dashboardRegions:regions];
continue;
}
if (!widget->isScrollbar())
continue;
// FIXME: This should really pass an appropriate clip, but our first try got it wrong, and
// it's not common to need this to be correct in Dashboard widgets.
NSRect bounds = widget->frameRect();
[self _addControlRect:bounds clip:bounds fromView:documentView toDashboardRegions:regions];
}
}
- (void)_addScrollerDashboardRegions:(NSMutableDictionary *)regions from:(NSArray *)views
{
// Add scroller regions for NSScroller and WebCore scrollbars
NSUInteger count = [views count];
for (NSUInteger i = 0; i < count; i++) {
NSView *view = [views objectAtIndex:i];
if ([view isKindOfClass:[WebHTMLView class]]) {
if (Frame* coreFrame = core([(WebHTMLView*)view _frame])) {
if (FrameView* coreView = coreFrame->view())
[self _addScrollerDashboardRegionsForFrameView:coreView dashboardRegions:regions];
}
} else if ([view isKindOfClass:[NSScroller class]]) {
// AppKit places absent scrollers at -100,-100
if ([view frame].origin.y < 0)
continue;
[self _addControlRect:[view bounds] clip:[view visibleRect] fromView:view toDashboardRegions:regions];
}
[self _addScrollerDashboardRegions:regions from:[view subviews]];
}
}
- (void)_addScrollerDashboardRegions:(NSMutableDictionary *)regions
{
[self _addScrollerDashboardRegions:regions from:[self subviews]];
}
- (NSDictionary *)_dashboardRegions
{
// Only return regions from main frame.
Frame* mainFrame = [self _mainCoreFrame];
if (!mainFrame)
return nil;
const Vector<AnnotatedRegionValue>& regions = mainFrame->document()->annotatedRegions();
size_t size = regions.size();
NSMutableDictionary *webRegions = [NSMutableDictionary dictionaryWithCapacity:size];
for (size_t i = 0; i < size; i++) {
const AnnotatedRegionValue& region = regions[i];
if (region.type == StyleDashboardRegion::None)
continue;
NSString *label = region.label;
WebDashboardRegionType type = WebDashboardRegionTypeNone;
if (region.type == StyleDashboardRegion::Circle)
type = WebDashboardRegionTypeCircle;
else if (region.type == StyleDashboardRegion::Rectangle)
type = WebDashboardRegionTypeRectangle;
NSMutableArray *regionValues = [webRegions objectForKey:label];
if (!regionValues) {
regionValues = [[NSMutableArray alloc] initWithCapacity:1];
[webRegions setObject:regionValues forKey:label];
[regionValues release];
}
WebDashboardRegion *webRegion = [[WebDashboardRegion alloc] initWithRect:pixelSnappedIntRect(region.bounds) clip:pixelSnappedIntRect(region.clip) type:type];
[regionValues addObject:webRegion];
[webRegion release];
}
[self _addScrollerDashboardRegions:webRegions];
return webRegions;
}
- (void)_setDashboardBehavior:(WebDashboardBehavior)behavior to:(BOOL)flag
{
// FIXME: Remove this blanket assignment once Dashboard and Dashcode implement
// specific support for the backward compatibility mode flag.
if (behavior == WebDashboardBehaviorAllowWheelScrolling && flag == NO && _private->page)
_private->page->settings()->setUsesDashboardBackwardCompatibilityMode(true);
switch (behavior) {
case WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows: {
_private->dashboardBehaviorAlwaysSendMouseEventsToAllWindows = flag;
break;
}
case WebDashboardBehaviorAlwaysSendActiveNullEventsToPlugIns: {
_private->dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns = flag;
break;
}
case WebDashboardBehaviorAlwaysAcceptsFirstMouse: {
_private->dashboardBehaviorAlwaysAcceptsFirstMouse = flag;
break;
}
case WebDashboardBehaviorAllowWheelScrolling: {
_private->dashboardBehaviorAllowWheelScrolling = flag;
break;
}
case WebDashboardBehaviorUseBackwardCompatibilityMode: {
if (_private->page)
_private->page->settings()->setUsesDashboardBackwardCompatibilityMode(flag);
#if ENABLE(LEGACY_CSS_VENDOR_PREFIXES)
RuntimeEnabledFeatures::setLegacyCSSVendorPrefixesEnabled(flag);
#endif
break;
}
}
// Pre-HTML5 parser quirks should be enabled if Dashboard is in backward
// compatibility mode. See <rdar://problem/8175982>.
if (_private->page)
_private->page->settings()->setUsePreHTML5ParserQuirks([self _needsPreHTML5ParserQuirks]);
}
- (BOOL)_dashboardBehavior:(WebDashboardBehavior)behavior
{
switch (behavior) {
case WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows: {
return _private->dashboardBehaviorAlwaysSendMouseEventsToAllWindows;
}
case WebDashboardBehaviorAlwaysSendActiveNullEventsToPlugIns: {
return _private->dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns;
}
case WebDashboardBehaviorAlwaysAcceptsFirstMouse: {
return _private->dashboardBehaviorAlwaysAcceptsFirstMouse;
}
case WebDashboardBehaviorAllowWheelScrolling: {
return _private->dashboardBehaviorAllowWheelScrolling;
}
case WebDashboardBehaviorUseBackwardCompatibilityMode: {
return _private->page && _private->page->settings()->usesDashboardBackwardCompatibilityMode();
}
}
return NO;
}
#endif /* ENABLE(DASHBOARD_SUPPORT) */
+ (void)_setShouldUseFontSmoothing:(BOOL)f
{
Font::setShouldUseSmoothing(f);
}
+ (BOOL)_shouldUseFontSmoothing
{
return Font::shouldUseSmoothing();
}
+ (void)_setUsesTestModeFocusRingColor:(BOOL)f
{
setUsesTestModeFocusRingColor(f);
}
+ (BOOL)_usesTestModeFocusRingColor
{
return usesTestModeFocusRingColor();
}
- (void)setAlwaysShowVerticalScroller:(BOOL)flag
{
WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
if (flag) {
[scrollview setVerticalScrollingMode:ScrollbarAlwaysOn andLock:YES];
} else {
[scrollview setVerticalScrollingModeLocked:NO];
[scrollview setVerticalScrollingMode:ScrollbarAuto andLock:NO];
}
}
- (BOOL)alwaysShowVerticalScroller
{
WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
return [scrollview verticalScrollingModeLocked] && [scrollview verticalScrollingMode] == ScrollbarAlwaysOn;
}
- (void)setAlwaysShowHorizontalScroller:(BOOL)flag
{
WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
if (flag) {
[scrollview setHorizontalScrollingMode:ScrollbarAlwaysOn andLock:YES];
} else {
[scrollview setHorizontalScrollingModeLocked:NO];
[scrollview setHorizontalScrollingMode:ScrollbarAuto andLock:NO];
}
}
- (void)setProhibitsMainFrameScrolling:(BOOL)prohibits
{
if (Frame* mainFrame = [self _mainCoreFrame])
mainFrame->view()->setProhibitsScrolling(prohibits);
}
- (BOOL)alwaysShowHorizontalScroller
{
WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
return [scrollview horizontalScrollingModeLocked] && [scrollview horizontalScrollingMode] == ScrollbarAlwaysOn;
}
- (void)_setInViewSourceMode:(BOOL)flag
{
if (Frame* mainFrame = [self _mainCoreFrame])
mainFrame->setInViewSourceMode(flag);
}
- (BOOL)_inViewSourceMode
{
Frame* mainFrame = [self _mainCoreFrame];
return mainFrame && mainFrame->inViewSourceMode();
}
- (void)_setUseFastImageScalingMode:(BOOL)flag
{
if (_private->page && _private->page->inLowQualityImageInterpolationMode() != flag) {
_private->page->setInLowQualityImageInterpolationMode(flag);
[self setNeedsDisplay:YES];
}
}
- (BOOL)_inFastImageScalingMode
{
if (_private->page)
return _private->page->inLowQualityImageInterpolationMode();
return NO;
}
- (BOOL)_cookieEnabled
{
if (_private->page)
return _private->page->settings()->cookieEnabled();
return YES;
}
- (void)_setCookieEnabled:(BOOL)enable
{
if (_private->page)
_private->page->settings()->setCookieEnabled(enable);
}
- (void)_setAdditionalWebPlugInPaths:(NSArray *)newPaths
{
if (!_private->pluginDatabase)
_private->pluginDatabase = [[WebPluginDatabase alloc] init];
[_private->pluginDatabase setPlugInPaths:newPaths];
[_private->pluginDatabase refresh];
}
- (void)_attachScriptDebuggerToAllFrames
{
for (Frame* frame = [self _mainCoreFrame]; frame; frame = frame->tree()->traverseNext())
[kit(frame) _attachScriptDebugger];
}
- (void)_detachScriptDebuggerFromAllFrames
{
for (Frame* frame = [self _mainCoreFrame]; frame; frame = frame->tree()->traverseNext())
[kit(frame) _detachScriptDebugger];
}
- (void)setBackgroundColor:(NSColor *)backgroundColor
{
if ([_private->backgroundColor isEqual:backgroundColor])
return;
id old = _private->backgroundColor;
_private->backgroundColor = [backgroundColor retain];
[old release];
[[self mainFrame] _updateBackgroundAndUpdatesWhileOffscreen];
}
- (NSColor *)backgroundColor
{
return _private->backgroundColor;
}
- (BOOL)defersCallbacks
{
if (!_private->page)
return NO;
return _private->page->defersLoading();
}
- (void)setDefersCallbacks:(BOOL)defer
{
if (!_private->page)
return;
return _private->page->setDefersLoading(defer);
}
// For backwards compatibility with the WebBackForwardList API, we honor both
// a per-WebView and a per-preferences setting for whether to use the page cache.
- (BOOL)usesPageCache
{
return _private->usesPageCache && [[self preferences] usesPageCache];
}
- (void)setUsesPageCache:(BOOL)usesPageCache
{
_private->usesPageCache = usesPageCache;
// Update our own settings and post the public notification only
[self _preferencesChanged:[self preferences]];
[[self preferences] _postPreferencesChangedAPINotification];
}
- (WebHistoryItem *)_globalHistoryItem
{
if (!_private)
return nil;
return kit(_private->_globalHistoryItem.get());
}
- (void)_setGlobalHistoryItem:(HistoryItem*)historyItem
{
_private->_globalHistoryItem = historyItem;
}
- (WebTextIterator *)textIteratorForRect:(NSRect)rect
{
IntPoint rectStart(rect.origin.x, rect.origin.y);
IntPoint rectEnd(rect.origin.x + rect.size.width, rect.origin.y + rect.size.height);
Frame* coreFrame = [self _mainCoreFrame];
if (!coreFrame)
return nil;
VisibleSelection selectionInsideRect(coreFrame->visiblePositionForPoint(rectStart), coreFrame->visiblePositionForPoint(rectEnd));
return [[[WebTextIterator alloc] initWithRange:kit(selectionInsideRect.toNormalizedRange().get())] autorelease];
}
- (void)handleAuthenticationForResource:(id)identifier challenge:(NSURLAuthenticationChallenge *)challenge fromDataSource:(WebDataSource *)dataSource
{
NSWindow *window = [self hostWindow] ? [self hostWindow] : [self window];
[[WebPanelAuthenticationHandler sharedHandler] startAuthentication:challenge window:window];
}
- (void)_clearUndoRedoOperations
{
if (!_private->page)
return;
_private->page->clearUndoRedoOperations();
}
- (void)_executeCoreCommandByName:(NSString *)name value:(NSString *)value
{
Frame* coreFrame = [self _mainCoreFrame];
if (!coreFrame)
return;
coreFrame->editor().command(name).execute(value);
}
- (void)_setCustomHTMLTokenizerTimeDelay:(double)timeDelay
{
if (!_private->page)
return;
return _private->page->setCustomHTMLTokenizerTimeDelay(timeDelay);
}
- (void)_setCustomHTMLTokenizerChunkSize:(int)chunkSize
{
if (!_private->page)
return;
return _private->page->setCustomHTMLTokenizerChunkSize(chunkSize);
}
- (void)_clearMainFrameName
{
_private->page->mainFrame()->tree()->clearName();
}
- (void)setSelectTrailingWhitespaceEnabled:(BOOL)flag
{
if (_private->page->settings()->selectTrailingWhitespaceEnabled() != flag) {
_private->page->settings()->setSelectTrailingWhitespaceEnabled(flag);
[self setSmartInsertDeleteEnabled:!flag];
}
}
- (BOOL)isSelectTrailingWhitespaceEnabled
{
return _private->page->settings()->selectTrailingWhitespaceEnabled();
}
- (void)setMemoryCacheDelegateCallsEnabled:(BOOL)enabled
{
_private->page->setMemoryCacheClientCallsEnabled(enabled);
}
- (BOOL)areMemoryCacheDelegateCallsEnabled
{
return _private->page->areMemoryCacheClientCallsEnabled();
}
+ (NSCursor *)_pointingHandCursor
{
return handCursor().platformCursor();
}
- (BOOL)_postsAcceleratedCompositingNotifications
{
#if USE(ACCELERATED_COMPOSITING)
return _private->postsAcceleratedCompositingNotifications;
#else
return NO;
#endif
}
- (void)_setPostsAcceleratedCompositingNotifications:(BOOL)flag
{
#if USE(ACCELERATED_COMPOSITING)
_private->postsAcceleratedCompositingNotifications = flag;
#endif
}
- (BOOL)_isUsingAcceleratedCompositing
{
#if USE(ACCELERATED_COMPOSITING)
Frame* coreFrame = [self _mainCoreFrame];
for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
NSView *documentView = [[kit(frame) frameView] documentView];
if ([documentView isKindOfClass:[WebHTMLView class]] && [(WebHTMLView *)documentView _isUsingAcceleratedCompositing])
return YES;
}
#endif
return NO;
}
- (void)_setBaseCTM:(CGAffineTransform)transform forContext:(CGContextRef)context
{
WKSetBaseCTM(context, transform);
}
- (BOOL)interactiveFormValidationEnabled
{
return _private->interactiveFormValidationEnabled;
}
- (void)setInteractiveFormValidationEnabled:(BOOL)enabled
{
_private->interactiveFormValidationEnabled = enabled;
}
- (int)validationMessageTimerMagnification
{
return _private->validationMessageTimerMagnification;
}
- (void)setValidationMessageTimerMagnification:(int)newValue
{
_private->validationMessageTimerMagnification = newValue;
}
- (BOOL)_isSoftwareRenderable
{
#if USE(ACCELERATED_COMPOSITING)
Frame* coreFrame = [self _mainCoreFrame];
for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
if (FrameView* view = frame->view()) {
if (!view->isSoftwareRenderable())
return NO;
}
}
#endif
return YES;
}
- (void)_setIncludesFlattenedCompositingLayersWhenDrawingToBitmap:(BOOL)flag
{
_private->includesFlattenedCompositingLayersWhenDrawingToBitmap = flag;
}
- (BOOL)_includesFlattenedCompositingLayersWhenDrawingToBitmap
{
return _private->includesFlattenedCompositingLayersWhenDrawingToBitmap;
}
- (void)setTracksRepaints:(BOOL)flag
{
Frame* coreFrame = [self _mainCoreFrame];
if (FrameView* view = coreFrame->view())
view->setTracksRepaints(flag);
}
- (BOOL)isTrackingRepaints
{
Frame* coreFrame = [self _mainCoreFrame];
if (FrameView* view = coreFrame->view())
return view->isTrackingRepaints();
return NO;
}
- (void)resetTrackedRepaints
{
Frame* coreFrame = [self _mainCoreFrame];
if (FrameView* view = coreFrame->view())
view->resetTrackedRepaints();
}
- (NSArray*)trackedRepaintRects
{
Frame* coreFrame = [self _mainCoreFrame];
FrameView* view = coreFrame->view();
if (!view || !view->isTrackingRepaints())
return nil;
const Vector<IntRect>& repaintRects = view->trackedRepaintRects();
NSMutableArray* rectsArray = [[NSMutableArray alloc] initWithCapacity:repaintRects.size()];
for (unsigned i = 0; i < repaintRects.size(); ++i)
[rectsArray addObject:[NSValue valueWithRect:pixelSnappedIntRect(repaintRects[i])]];
return [rectsArray autorelease];
}
- (NSPasteboard *)_insertionPasteboard
{
return _private ? _private->insertionPasteboard : nil;
}
+ (void)_addOriginAccessWhitelistEntryWithSourceOrigin:(NSString *)sourceOrigin destinationProtocol:(NSString *)destinationProtocol destinationHost:(NSString *)destinationHost allowDestinationSubdomains:(BOOL)allowDestinationSubdomains
{
SecurityPolicy::addOriginAccessWhitelistEntry(*SecurityOrigin::createFromString(sourceOrigin), destinationProtocol, destinationHost, allowDestinationSubdomains);
}
+ (void)_removeOriginAccessWhitelistEntryWithSourceOrigin:(NSString *)sourceOrigin destinationProtocol:(NSString *)destinationProtocol destinationHost:(NSString *)destinationHost allowDestinationSubdomains:(BOOL)allowDestinationSubdomains
{
SecurityPolicy::removeOriginAccessWhitelistEntry(*SecurityOrigin::createFromString(sourceOrigin), destinationProtocol, destinationHost, allowDestinationSubdomains);
}
+ (void)_resetOriginAccessWhitelists
{
SecurityPolicy::resetOriginAccessWhitelists();
}
- (BOOL)_isViewVisible
{
if (![self window])
return false;
if (![[self window] isVisible])
return false;
if ([self isHiddenOrHasHiddenAncestor])
return false;
return true;
}
- (void)_updateVisibilityState
{
if (_private && _private->page)
[self _setVisibilityState:([self _isViewVisible] ? WebPageVisibilityStateVisible : WebPageVisibilityStateHidden) isInitialState:NO];
}
- (void)_updateActiveState
{
if (_private && _private->page)
_private->page->focusController()->setActive([[self window] _hasKeyAppearance]);
}
static Vector<String> toStringVector(NSArray* patterns)
{
Vector<String> patternsVector;
NSUInteger count = [patterns count];
if (!count)
return patternsVector;
for (NSUInteger i = 0; i < count; ++i) {
id entry