1/* 2 * Copyright (C) 2005-2013 Apple Inc. All rights reserved. 3 * Copyright (C) 2006 David Smith (catfish.man@gmail.com) 4 * Copyright (C) 2010 Igalia S.L 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of Apple Inc. ("Apple") nor the names of 16 * its contributors may be used to endorse or promote products derived 17 * from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31#import "WebViewInternal.h" 32#import "WebViewData.h" 33 34#import "DOMCSSStyleDeclarationInternal.h" 35#import "DOMDocumentInternal.h" 36#import "DOMNodeInternal.h" 37#import "DOMRangeInternal.h" 38#import "WebAlternativeTextClient.h" 39#import "WebApplicationCache.h" 40#import "WebBackForwardListInternal.h" 41#import "WebBaseNetscapePluginView.h" 42#import "WebCache.h" 43#import "WebChromeClient.h" 44#import "WebDOMOperationsPrivate.h" 45#import "WebDataSourceInternal.h" 46#import "WebDatabaseManagerPrivate.h" 47#import "WebDefaultEditingDelegate.h" 48#import "WebDefaultPolicyDelegate.h" 49#import "WebDefaultUIDelegate.h" 50#import "WebDelegateImplementationCaching.h" 51#import "WebDeviceOrientationClient.h" 52#import "WebDeviceOrientationProvider.h" 53#import "WebDocument.h" 54#import "WebDocumentInternal.h" 55#import "WebDownload.h" 56#import "WebDownloadInternal.h" 57#import "WebDragClient.h" 58#import "WebDynamicScrollBarsViewInternal.h" 59#import "WebEditingDelegate.h" 60#import "WebEditorClient.h" 61#import "WebFormDelegatePrivate.h" 62#import "WebFrameInternal.h" 63#import "WebFrameLoaderClient.h" 64#import "WebFrameNetworkingContext.h" 65#import "WebFrameViewInternal.h" 66#import "WebGeolocationClient.h" 67#import "WebGeolocationPositionInternal.h" 68#import "WebHTMLRepresentation.h" 69#import "WebHTMLViewInternal.h" 70#import "WebHistoryItemInternal.h" 71#import "WebIconDatabaseInternal.h" 72#import "WebInspector.h" 73#import "WebInspectorClient.h" 74#import "WebKitErrors.h" 75#import "WebKitFullScreenListener.h" 76#import "WebKitLogging.h" 77#import "WebKitNSStringExtras.h" 78#import "WebKitStatisticsPrivate.h" 79#import "WebKitSystemBits.h" 80#import "WebKitVersionChecks.h" 81#import "WebLocalizableStrings.h" 82#import "WebNSDataExtras.h" 83#import "WebNSDataExtrasPrivate.h" 84#import "WebNSDictionaryExtras.h" 85#import "WebNSURLExtras.h" 86#import "WebNSURLRequestExtras.h" 87#import "WebNSViewExtras.h" 88#import "WebNodeHighlight.h" 89#import "WebNotificationClient.h" 90#import "WebPDFView.h" 91#import "WebPanelAuthenticationHandler.h" 92#import "WebPlatformStrategies.h" 93#import "WebPluginDatabase.h" 94#import "WebPolicyDelegate.h" 95#import "WebPreferenceKeysPrivate.h" 96#import "WebPreferencesPrivate.h" 97#import "WebProgressTrackerClient.h" 98#import "WebScriptDebugDelegate.h" 99#import "WebScriptWorldInternal.h" 100#import "WebStorageManagerInternal.h" 101#import "WebSystemInterface.h" 102#import "WebTextCompletionController.h" 103#import "WebTextIterator.h" 104#import "WebUIDelegate.h" 105#import "WebUIDelegatePrivate.h" 106#import "WebUserMediaClient.h" 107#import "WebViewGroup.h" 108#import <CoreFoundation/CFSet.h> 109#import <Foundation/NSURLConnection.h> 110#import <JavaScriptCore/APICast.h> 111#import <JavaScriptCore/JSValueRef.h> 112#import <WebCore/AlternativeTextUIController.h> 113#import <WebCore/AnimationController.h> 114#import <WebCore/ApplicationCacheStorage.h> 115#import <WebCore/BackForwardController.h> 116#import <WebCore/BackForwardList.h> 117#import <WebCore/MemoryCache.h> 118#import <WebCore/Chrome.h> 119#import <WebCore/ColorMac.h> 120#import <WebCore/Cursor.h> 121#import <WebCore/DatabaseManager.h> 122#import <WebCore/Document.h> 123#import <WebCore/DocumentLoader.h> 124#import <WebCore/DragController.h> 125#import <WebCore/DragData.h> 126#import <WebCore/Editor.h> 127#import <WebCore/EventHandler.h> 128#import <WebCore/ExceptionHandlers.h> 129#import <WebCore/FocusController.h> 130#import <WebCore/FrameLoader.h> 131#import <WebCore/FrameSelection.h> 132#import <WebCore/FrameTree.h> 133#import <WebCore/FrameView.h> 134#import <WebCore/GCController.h> 135#import <WebCore/GeolocationController.h> 136#import <WebCore/GeolocationError.h> 137#import <WebCore/HTMLMediaElement.h> 138#import <WebCore/HTMLNames.h> 139#import <WebCore/HistoryController.h> 140#import <WebCore/HistoryItem.h> 141#import <WebCore/IconDatabase.h> 142#import <WebCore/JSCSSStyleDeclaration.h> 143#import <WebCore/JSDocument.h> 144#import <WebCore/JSElement.h> 145#import <WebCore/JSNodeList.h> 146#import <WebCore/JSNotification.h> 147#import <WebCore/Logging.h> 148#import <WebCore/MIMETypeRegistry.h> 149#import <WebCore/MainFrame.h> 150#import <WebCore/MemoryPressureHandler.h> 151#import <WebCore/NodeList.h> 152#import <WebCore/Notification.h> 153#import <WebCore/NotificationController.h> 154#import <WebCore/Page.h> 155#import <WebCore/PageCache.h> 156#import <WebCore/PageGroup.h> 157#import <WebCore/PlatformEventFactoryMac.h> 158#import <WebCore/ProgressTracker.h> 159#import <WebCore/RenderView.h> 160#import <WebCore/RenderWidget.h> 161#import <WebCore/ResourceHandle.h> 162#import <WebCore/ResourceLoadScheduler.h> 163#import <WebCore/ResourceRequest.h> 164#import <WebCore/RuntimeApplicationChecks.h> 165#import <WebCore/RuntimeEnabledFeatures.h> 166#import <WebCore/SchemeRegistry.h> 167#import <WebCore/ScriptController.h> 168#import <WebCore/SecurityOrigin.h> 169#import <WebCore/SecurityPolicy.h> 170#import <WebCore/Settings.h> 171#import <WebCore/StyleProperties.h> 172#import <WebCore/TextResourceDecoder.h> 173#import <WebCore/ThreadCheck.h> 174#import <WebCore/UserAgent.h> 175#import <WebCore/WebCoreObjCExtras.h> 176#import <WebCore/WebCoreView.h> 177#import <WebCore/Widget.h> 178#import <WebKitLegacy/DOM.h> 179#import <WebKitLegacy/DOMExtensions.h> 180#import <WebKitLegacy/DOMPrivate.h> 181#import <WebKitSystemInterface.h> 182#import <bindings/ScriptValue.h> 183#import <mach-o/dyld.h> 184#import <objc/objc-auto.h> 185#import <objc/runtime.h> 186#import <runtime/ArrayPrototype.h> 187#import <runtime/DateInstance.h> 188#import <runtime/InitializeThreading.h> 189#import <runtime/JSLock.h> 190#import <runtime/JSCJSValue.h> 191#import <wtf/Assertions.h> 192#import <wtf/HashTraits.h> 193#import <wtf/MainThread.h> 194#import <wtf/ObjcRuntimeExtras.h> 195#import <wtf/RefCountedLeakCounter.h> 196#import <wtf/RefPtr.h> 197#import <wtf/RunLoop.h> 198#import <wtf/StdLibExtras.h> 199 200#if !PLATFORM(IOS) 201#import "WebContextMenuClient.h" 202#import "WebFullScreenController.h" 203#import "WebNSEventExtras.h" 204#import "WebNSObjectExtras.h" 205#import "WebNSPasteboardExtras.h" 206#import "WebNSPrintOperationExtras.h" 207#import "WebPDFView.h" 208#import <WebCore/WebVideoFullscreenController.h> 209#else 210#import "MemoryMeasure.h" 211#import "WebCaretChangeListener.h" 212#import "WebChromeClientIOS.h" 213#import "WebDefaultFormDelegate.h" 214#import "WebDefaultFrameLoadDelegate.h" 215#import "WebDefaultResourceLoadDelegate.h" 216#import "WebDefaultUIKitDelegate.h" 217#import "WebFixedPositionContent.h" 218#import "WebMailDelegate.h" 219#import "WebNSUserDefaultsExtras.h" 220#import "WebPDFViewIOS.h" 221#import "WebPlainWhiteView.h" 222#import "WebPluginController.h" 223#import "WebPolicyDelegatePrivate.h" 224#import "WebSQLiteDatabaseTrackerClient.h" 225#import "WebStorageManagerPrivate.h" 226#import "WebUIKitSupport.h" 227#import "WebVisiblePosition.h" 228#import <CFNetwork/CFURLCachePriv.h> 229#import <MobileGestalt.h> 230#import <WebCore/EventNames.h> 231#import <WebCore/FontCache.h> 232#import <WebCore/GraphicsLayer.h> 233#import <WebCore/IconController.h> 234#import <WebCore/LegacyTileCache.h> 235#import <WebCore/NetworkStateNotifier.h> 236#import <WebCore/RuntimeApplicationChecksIOS.h> 237#import <WebCore/SQLiteDatabaseTracker.h> 238#import <WebCore/SmartReplace.h> 239#import <WebCore/TextRun.h> 240#import <WebCore/TileControllerMemoryHandlerIOS.h> 241#import <WebCore/WAKWindow.h> 242#import <WebCore/WKView.h> 243#import <WebCore/WebCoreThread.h> 244#import <WebCore/WebCoreThreadMessage.h> 245#import <WebCore/WebCoreThreadRun.h> 246#import <WebCore/WebEvent.h> 247#import <WebCore/WebVideoFullscreenControllerAVKit.h> 248#import <dispatch/private.h> 249#import <wtf/FastMalloc.h> 250#endif // !PLATFORM(IOS) 251 252#if ENABLE(DASHBOARD_SUPPORT) 253#import <WebKitLegacy/WebDashboardRegion.h> 254#endif 255 256#if ENABLE(DISK_IMAGE_CACHE) && PLATFORM(IOS) 257#import "WebDiskImageCacheClientIOS.h" 258#import <WebCore/DiskImageCacheIOS.h> 259#endif 260 261#if ENABLE(REMOTE_INSPECTOR) 262#import <JavaScriptCore/RemoteInspector.h> 263#if PLATFORM(IOS) 264#import "WebIndicateLayer.h" 265#endif 266#endif 267 268#if USE(GLIB) 269#import <glib.h> 270#endif 271 272#if USE(QUICK_LOOK) 273#include <WebCore/QuickLook.h> 274#endif 275 276#if ENABLE(TOUCH_EVENTS) 277#import <WebCore/WebEventRegion.h> 278#endif 279 280#if ENABLE(DISK_IMAGE_CACHE) 281#import "WebDiskImageCacheClientIOS.h" 282#import <WebCore/DiskImageCacheIOS.h> 283#endif 284 285#if ENABLE(GAMEPAD) 286#import <WebCore/HIDGamepadProvider.h> 287#endif 288 289#if !PLATFORM(IOS) 290@interface NSSpellChecker (WebNSSpellCheckerDetails) 291- (void)_preflightChosenSpellServer; 292@end 293 294@interface NSView (WebNSViewDetails) 295- (NSView *)_hitTest:(NSPoint *)aPoint dragTypes:(NSSet *)types; 296- (void)_autoscrollForDraggingInfo:(id)dragInfo timeDelta:(NSTimeInterval)repeatDelta; 297- (BOOL)_shouldAutoscrollForDraggingInfo:(id)dragInfo; 298- (void)_windowChangedKeyState; 299@end 300 301@interface NSWindow (WebNSWindowDetails) 302- (id)_oldFirstResponderBeforeBecoming; 303- (void)_enableScreenUpdatesIfNeeded; 304- (BOOL)_wrapsCarbonWindow; 305- (BOOL)_hasKeyAppearance; 306@end 307#endif 308 309using namespace JSC; 310using namespace Inspector; 311using namespace WebCore; 312 313#define FOR_EACH_RESPONDER_SELECTOR(macro) \ 314macro(alignCenter) \ 315macro(alignJustified) \ 316macro(alignLeft) \ 317macro(alignRight) \ 318macro(capitalizeWord) \ 319macro(centerSelectionInVisibleArea) \ 320macro(changeAttributes) \ 321macro(changeBaseWritingDirection) \ 322macro(changeBaseWritingDirectionToLTR) \ 323macro(changeBaseWritingDirectionToRTL) \ 324macro(changeColor) \ 325macro(changeDocumentBackgroundColor) \ 326macro(changeFont) \ 327macro(changeSpelling) \ 328macro(checkSpelling) \ 329macro(complete) \ 330macro(copy) \ 331macro(copyFont) \ 332macro(cut) \ 333macro(delete) \ 334macro(deleteBackward) \ 335macro(deleteBackwardByDecomposingPreviousCharacter) \ 336macro(deleteForward) \ 337macro(deleteToBeginningOfLine) \ 338macro(deleteToBeginningOfParagraph) \ 339macro(deleteToEndOfLine) \ 340macro(deleteToEndOfParagraph) \ 341macro(deleteToMark) \ 342macro(deleteWordBackward) \ 343macro(deleteWordForward) \ 344macro(ignoreSpelling) \ 345macro(indent) \ 346macro(insertBacktab) \ 347macro(insertLineBreak) \ 348macro(insertNewline) \ 349macro(insertNewlineIgnoringFieldEditor) \ 350macro(insertParagraphSeparator) \ 351macro(insertTab) \ 352macro(insertTabIgnoringFieldEditor) \ 353macro(lowercaseWord) \ 354macro(makeBaseWritingDirectionLeftToRight) \ 355macro(makeBaseWritingDirectionRightToLeft) \ 356macro(makeTextWritingDirectionLeftToRight) \ 357macro(makeTextWritingDirectionNatural) \ 358macro(makeTextWritingDirectionRightToLeft) \ 359macro(moveBackward) \ 360macro(moveBackwardAndModifySelection) \ 361macro(moveDown) \ 362macro(moveDownAndModifySelection) \ 363macro(moveForward) \ 364macro(moveForwardAndModifySelection) \ 365macro(moveLeft) \ 366macro(moveLeftAndModifySelection) \ 367macro(moveParagraphBackwardAndModifySelection) \ 368macro(moveParagraphForwardAndModifySelection) \ 369macro(moveRight) \ 370macro(moveRightAndModifySelection) \ 371macro(moveToBeginningOfDocument) \ 372macro(moveToBeginningOfDocumentAndModifySelection) \ 373macro(moveToBeginningOfLine) \ 374macro(moveToBeginningOfLineAndModifySelection) \ 375macro(moveToBeginningOfParagraph) \ 376macro(moveToBeginningOfParagraphAndModifySelection) \ 377macro(moveToBeginningOfSentence) \ 378macro(moveToBeginningOfSentenceAndModifySelection) \ 379macro(moveToEndOfDocument) \ 380macro(moveToEndOfDocumentAndModifySelection) \ 381macro(moveToEndOfLine) \ 382macro(moveToEndOfLineAndModifySelection) \ 383macro(moveToEndOfParagraph) \ 384macro(moveToEndOfParagraphAndModifySelection) \ 385macro(moveToEndOfSentence) \ 386macro(moveToEndOfSentenceAndModifySelection) \ 387macro(moveToLeftEndOfLine) \ 388macro(moveToLeftEndOfLineAndModifySelection) \ 389macro(moveToRightEndOfLine) \ 390macro(moveToRightEndOfLineAndModifySelection) \ 391macro(moveUp) \ 392macro(moveUpAndModifySelection) \ 393macro(moveWordBackward) \ 394macro(moveWordBackwardAndModifySelection) \ 395macro(moveWordForward) \ 396macro(moveWordForwardAndModifySelection) \ 397macro(moveWordLeft) \ 398macro(moveWordLeftAndModifySelection) \ 399macro(moveWordRight) \ 400macro(moveWordRightAndModifySelection) \ 401macro(orderFrontSubstitutionsPanel) \ 402macro(outdent) \ 403macro(overWrite) \ 404macro(pageDown) \ 405macro(pageDownAndModifySelection) \ 406macro(pageUp) \ 407macro(pageUpAndModifySelection) \ 408macro(paste) \ 409macro(pasteAsPlainText) \ 410macro(pasteAsRichText) \ 411macro(pasteFont) \ 412macro(performFindPanelAction) \ 413macro(scrollLineDown) \ 414macro(scrollLineUp) \ 415macro(scrollPageDown) \ 416macro(scrollPageUp) \ 417macro(scrollToBeginningOfDocument) \ 418macro(scrollToEndOfDocument) \ 419macro(selectAll) \ 420macro(selectLine) \ 421macro(selectParagraph) \ 422macro(selectSentence) \ 423macro(selectToMark) \ 424macro(selectWord) \ 425macro(setMark) \ 426macro(showGuessPanel) \ 427macro(startSpeaking) \ 428macro(stopSpeaking) \ 429macro(subscript) \ 430macro(superscript) \ 431macro(swapWithMark) \ 432macro(takeFindStringFromSelection) \ 433macro(toggleBaseWritingDirection) \ 434macro(transpose) \ 435macro(underline) \ 436macro(unscript) \ 437macro(uppercaseWord) \ 438macro(yank) \ 439macro(yankAndSelect) \ 440 441#define WebKitOriginalTopPrintingMarginKey @"WebKitOriginalTopMargin" 442#define WebKitOriginalBottomPrintingMarginKey @"WebKitOriginalBottomMargin" 443 444#define KeyboardUIModeDidChangeNotification @"com.apple.KeyboardUIModeDidChange" 445#define AppleKeyboardUIMode CFSTR("AppleKeyboardUIMode") 446 447static BOOL s_didSetCacheModel; 448static WebCacheModel s_cacheModel = WebCacheModelDocumentViewer; 449 450#if PLATFORM(IOS) 451static Class s_pdfRepresentationClass; 452static Class s_pdfViewClass; 453#endif 454 455#ifndef NDEBUG 456static const char webViewIsOpen[] = "At least one WebView is still open."; 457#endif 458 459#if PLATFORM(IOS) 460@interface WebView(WebViewPrivate) 461- (void)_preferencesChanged:(WebPreferences *)preferences; 462- (void)_updateScreenScaleFromWindow; 463@end 464 465@interface NSURLCache (WebPrivate) 466- (CFURLCacheRef)_CFURLCache; 467@end 468#endif 469 470#if !PLATFORM(IOS) 471@interface NSObject (WebValidateWithoutDelegate) 472- (BOOL)validateUserInterfaceItemWithoutDelegate:(id <NSValidatedUserInterfaceItem>)item; 473@end 474#endif 475 476#if PLATFORM(IOS) 477@class _WebSafeForwarder; 478 479@interface _WebSafeAsyncForwarder : NSObject { 480 _WebSafeForwarder *_forwarder; 481} 482- (id)initWithForwarder:(_WebSafeForwarder *)forwarder; 483@end 484#endif 485 486@interface _WebSafeForwarder : NSObject 487{ 488 id target; // Non-retained. Don't retain delegates. 489 id defaultTarget; 490#if PLATFORM(IOS) 491 _WebSafeAsyncForwarder *asyncForwarder; 492 dispatch_once_t asyncForwarderPred; 493#endif 494} 495- (instancetype)initWithTarget:(id)target defaultTarget:(id)defaultTarget; 496#if PLATFORM(IOS) 497- (void)clearTarget; 498- (id)asyncForwarder; 499#endif 500@end 501 502FindOptions coreOptions(WebFindOptions options) 503{ 504 return (options & WebFindOptionsCaseInsensitive ? CaseInsensitive : 0) 505 | (options & WebFindOptionsAtWordStarts ? AtWordStarts : 0) 506 | (options & WebFindOptionsTreatMedialCapitalAsWordStart ? TreatMedialCapitalAsWordStart : 0) 507 | (options & WebFindOptionsBackwards ? Backwards : 0) 508 | (options & WebFindOptionsWrapAround ? WrapAround : 0) 509 | (options & WebFindOptionsStartInSelection ? StartInSelection : 0); 510} 511 512LayoutMilestones coreLayoutMilestones(WebLayoutMilestones milestones) 513{ 514 return (milestones & WebDidFirstLayout ? DidFirstLayout : 0) 515 | (milestones & WebDidFirstVisuallyNonEmptyLayout ? DidFirstVisuallyNonEmptyLayout : 0) 516 | (milestones & WebDidHitRelevantRepaintedObjectsAreaThreshold ? DidHitRelevantRepaintedObjectsAreaThreshold : 0); 517} 518 519WebLayoutMilestones kitLayoutMilestones(LayoutMilestones milestones) 520{ 521 return (milestones & DidFirstLayout ? WebDidFirstLayout : 0) 522 | (milestones & DidFirstVisuallyNonEmptyLayout ? WebDidFirstVisuallyNonEmptyLayout : 0) 523 | (milestones & DidHitRelevantRepaintedObjectsAreaThreshold ? WebDidHitRelevantRepaintedObjectsAreaThreshold : 0); 524} 525 526static WebPageVisibilityState kit(PageVisibilityState visibilityState) 527{ 528 switch (visibilityState) { 529 case PageVisibilityStateVisible: 530 return WebPageVisibilityStateVisible; 531 case PageVisibilityStateHidden: 532 return WebPageVisibilityStateHidden; 533 case PageVisibilityStatePrerender: 534 return WebPageVisibilityStatePrerender; 535 } 536 537 ASSERT_NOT_REACHED(); 538 return WebPageVisibilityStateVisible; 539} 540 541@interface WebView (WebFileInternal) 542#if !PLATFORM(IOS) 543- (float)_deviceScaleFactor; 544#endif 545- (BOOL)_isLoading; 546- (WebFrameView *)_frameViewAtWindowPoint:(NSPoint)point; 547- (WebFrame *)_focusedFrame; 548+ (void)_preflightSpellChecker; 549- (BOOL)_continuousCheckingAllowed; 550- (NSResponder *)_responderForResponderOperations; 551#if USE(GLIB) 552- (void)_clearGlibLoopObserver; 553#endif 554@end 555 556NSString *WebElementDOMNodeKey = @"WebElementDOMNode"; 557NSString *WebElementFrameKey = @"WebElementFrame"; 558NSString *WebElementImageKey = @"WebElementImage"; 559NSString *WebElementImageAltStringKey = @"WebElementImageAltString"; 560NSString *WebElementImageRectKey = @"WebElementImageRect"; 561NSString *WebElementImageURLKey = @"WebElementImageURL"; 562NSString *WebElementIsSelectedKey = @"WebElementIsSelected"; 563NSString *WebElementLinkLabelKey = @"WebElementLinkLabel"; 564NSString *WebElementLinkTargetFrameKey = @"WebElementTargetFrame"; 565NSString *WebElementLinkTitleKey = @"WebElementLinkTitle"; 566NSString *WebElementLinkURLKey = @"WebElementLinkURL"; 567NSString *WebElementMediaURLKey = @"WebElementMediaURL"; 568NSString *WebElementSpellingToolTipKey = @"WebElementSpellingToolTip"; 569NSString *WebElementTitleKey = @"WebElementTitle"; 570NSString *WebElementLinkIsLiveKey = @"WebElementLinkIsLive"; 571NSString *WebElementIsInScrollBarKey = @"WebElementIsInScrollBar"; 572NSString *WebElementIsContentEditableKey = @"WebElementIsContentEditableKey"; 573 574NSString *WebViewProgressStartedNotification = @"WebProgressStartedNotification"; 575NSString *WebViewProgressEstimateChangedNotification = @"WebProgressEstimateChangedNotification"; 576#if !PLATFORM(IOS) 577NSString *WebViewProgressFinishedNotification = @"WebProgressFinishedNotification"; 578#else 579NSString * const WebViewProgressEstimatedProgressKey = @"WebProgressEstimatedProgressKey"; 580NSString * const WebViewProgressBackgroundColorKey = @"WebProgressBackgroundColorKey"; 581#endif 582 583NSString * const WebViewDidBeginEditingNotification = @"WebViewDidBeginEditingNotification"; 584NSString * const WebViewDidChangeNotification = @"WebViewDidChangeNotification"; 585NSString * const WebViewDidEndEditingNotification = @"WebViewDidEndEditingNotification"; 586NSString * const WebViewDidChangeTypingStyleNotification = @"WebViewDidChangeTypingStyleNotification"; 587NSString * const WebViewDidChangeSelectionNotification = @"WebViewDidChangeSelectionNotification"; 588 589enum { WebViewVersion = 4 }; 590 591#define timedLayoutSize 4096 592 593static NSMutableSet *schemesWithRepresentationsSet; 594 595#if !PLATFORM(IOS) 596NSString *_WebCanGoBackKey = @"canGoBack"; 597NSString *_WebCanGoForwardKey = @"canGoForward"; 598NSString *_WebEstimatedProgressKey = @"estimatedProgress"; 599NSString *_WebIsLoadingKey = @"isLoading"; 600NSString *_WebMainFrameIconKey = @"mainFrameIcon"; 601NSString *_WebMainFrameTitleKey = @"mainFrameTitle"; 602NSString *_WebMainFrameURLKey = @"mainFrameURL"; 603NSString *_WebMainFrameDocumentKey = @"mainFrameDocument"; 604#endif 605 606#if USE(QUICK_LOOK) 607NSString *WebQuickLookFileNameKey = @"WebQuickLookFileNameKey"; 608NSString *WebQuickLookUTIKey = @"WebQuickLookUTIKey"; 609#endif 610 611NSString *_WebViewDidStartAcceleratedCompositingNotification = @"_WebViewDidStartAcceleratedCompositing"; 612NSString * const WebViewWillCloseNotification = @"WebViewWillCloseNotification"; 613 614#if ENABLE(REMOTE_INSPECTOR) 615// FIXME: Legacy, remove this, switch to something from JavaScriptCore Inspector::RemoteInspectorServer. 616NSString *_WebViewRemoteInspectorHasSessionChangedNotification = @"_WebViewRemoteInspectorHasSessionChangedNotification"; 617#endif 618 619NSString *WebKitKerningAndLigaturesEnabledByDefaultDefaultsKey = @"WebKitKerningAndLigaturesEnabledByDefault"; 620 621@interface WebProgressItem : NSObject 622{ 623@public 624 long long bytesReceived; 625 long long estimatedLength; 626} 627@end 628 629@implementation WebProgressItem 630@end 631 632static BOOL continuousSpellCheckingEnabled; 633#if !PLATFORM(IOS) 634static BOOL grammarCheckingEnabled; 635static BOOL automaticQuoteSubstitutionEnabled; 636static BOOL automaticLinkDetectionEnabled; 637static BOOL automaticDashSubstitutionEnabled; 638static BOOL automaticTextReplacementEnabled; 639static BOOL automaticSpellingCorrectionEnabled; 640#endif 641 642@implementation WebView (AllWebViews) 643 644static CFSetCallBacks NonRetainingSetCallbacks = { 645 0, 646 NULL, 647 NULL, 648 CFCopyDescription, 649 CFEqual, 650 CFHash 651}; 652 653static CFMutableSetRef allWebViewsSet; 654 655+ (void)_makeAllWebViewsPerformSelector:(SEL)selector 656{ 657 if (!allWebViewsSet) 658 return; 659 660 [(NSMutableSet *)allWebViewsSet makeObjectsPerformSelector:selector]; 661} 662 663- (void)_removeFromAllWebViewsSet 664{ 665 if (allWebViewsSet) 666 CFSetRemoveValue(allWebViewsSet, self); 667} 668 669- (void)_addToAllWebViewsSet 670{ 671 if (!allWebViewsSet) 672 allWebViewsSet = CFSetCreateMutable(NULL, 0, &NonRetainingSetCallbacks); 673 674 CFSetSetValue(allWebViewsSet, self); 675} 676 677@end 678 679@implementation WebView (WebPrivate) 680 681static String webKitBundleVersionString() 682{ 683 return [[NSBundle bundleForClass:[WebView class]] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey]; 684} 685 686+ (NSString *)_standardUserAgentWithApplicationName:(NSString *)applicationName 687{ 688 return standardUserAgentWithApplicationName(applicationName, webKitBundleVersionString()); 689} 690 691#if PLATFORM(IOS) 692- (void)_setBrowserUserAgentProductVersion:(NSString *)productVersion buildVersion:(NSString *)buildVersion bundleVersion:(NSString *)bundleVersion 693{ 694 [self setApplicationNameForUserAgent:[NSString stringWithFormat:@"Version/%@ Mobile/%@ Safari/%@", productVersion, buildVersion, bundleVersion]]; 695} 696 697- (void)_setUIWebViewUserAgentWithBuildVersion:(NSString *)buildVersion 698{ 699 [self setApplicationNameForUserAgent:[@"Mobile/" stringByAppendingString:buildVersion]]; 700} 701#endif // PLATFORM(IOS) 702 703+ (void)_reportException:(JSValueRef)exception inContext:(JSContextRef)context 704{ 705 if (!exception || !context) 706 return; 707 708 JSC::ExecState* execState = toJS(context); 709 JSLockHolder lock(execState); 710 711 // Make sure the context has a DOMWindow global object, otherwise this context didn't originate from a WebView. 712 if (!toJSDOMWindow(execState->lexicalGlobalObject())) 713 return; 714 715 reportException(execState, toJS(execState, exception)); 716} 717 718static void WebKitInitializeApplicationCachePathIfNecessary() 719{ 720 static BOOL initialized = NO; 721 if (initialized) 722 return; 723 724 NSString *appName = [[NSBundle mainBundle] bundleIdentifier]; 725 if (!appName) 726 appName = [[NSProcessInfo processInfo] processName]; 727#if PLATFORM(IOS) 728 if (WebCore::applicationIsMobileSafari() || WebCore::applicationIsWebApp()) 729 appName = @"com.apple.WebAppCache"; 730#endif 731 732 ASSERT(appName); 733 734 NSString* cacheDir = [NSString _webkit_localCacheDirectoryWithBundleIdentifier:appName]; 735 736 cacheStorage().setCacheDirectory(cacheDir); 737 initialized = YES; 738} 739 740static bool shouldEnableLoadDeferring() 741{ 742 return !applicationIsAdobeInstaller(); 743} 744 745static bool shouldRestrictWindowFocus() 746{ 747#if PLATFORM(IOS) 748 return true; 749#else 750 return !applicationIsHRBlock(); 751#endif 752} 753 754- (void)_dispatchPendingLoadRequests 755{ 756 resourceLoadScheduler()->servePendingRequests(); 757} 758 759#if !PLATFORM(IOS) 760- (void)_registerDraggedTypes 761{ 762 NSArray *editableTypes = [WebHTMLView _insertablePasteboardTypes]; 763 NSArray *URLTypes = [NSPasteboard _web_dragTypesForURL]; 764 NSMutableSet *types = [[NSMutableSet alloc] initWithArray:editableTypes]; 765 [types addObjectsFromArray:URLTypes]; 766 [self registerForDraggedTypes:[types allObjects]]; 767 [types release]; 768} 769 770static bool needsOutlookQuirksScript() 771{ 772 static bool isOutlookNeedingQuirksScript = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_HTML5_PARSER) 773 && applicationIsMicrosoftOutlook(); 774 return isOutlookNeedingQuirksScript; 775} 776 777static NSString *leakOutlookQuirksUserScriptContents() 778{ 779 NSString *scriptPath = [[NSBundle bundleForClass:[WebView class]] pathForResource:@"OutlookQuirksUserScript" ofType:@"js"]; 780 NSStringEncoding encoding; 781 return [[NSString alloc] initWithContentsOfFile:scriptPath usedEncoding:&encoding error:0]; 782} 783 784-(void)_injectOutlookQuirksScript 785{ 786 static NSString *outlookQuirksScriptContents = leakOutlookQuirksUserScriptContents(); 787 core(self)->group().addUserScriptToWorld(*core([WebScriptWorld world]), 788 outlookQuirksScriptContents, URL(), Vector<String>(), Vector<String>(), InjectAtDocumentEnd, InjectInAllFrames); 789} 790#endif 791 792static bool shouldRespectPriorityInCSSAttributeSetters() 793{ 794#if PLATFORM(IOS) 795 static bool isStanzaNeedingAttributeSetterQuirk = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_CSS_ATTRIBUTE_SETTERS_IGNORING_PRIORITY) 796 && [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.lexcycle.stanza"]; 797 return isStanzaNeedingAttributeSetterQuirk; 798#else 799 static bool isIAdProducerNeedingAttributeSetterQuirk = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_CSS_ATTRIBUTE_SETTERS_IGNORING_PRIORITY) 800 && [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.iAdProducer"]; 801 return isIAdProducerNeedingAttributeSetterQuirk; 802#endif 803} 804 805#if PLATFORM(IOS) 806static bool shouldTransformsAffectOverflow() 807{ 808 static bool shouldTransformsAffectOverflow = !applicationIsOkCupid() || WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_CSS_TRANSFORMS_AFFECTING_OVERFLOW); 809 return shouldTransformsAffectOverflow; 810} 811 812static bool shouldDispatchJavaScriptWindowOnErrorEvents() 813{ 814 static bool shouldDispatchJavaScriptWindowOnErrorEvents = !applicationIsFacebook() || WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_WINDOW_ON_ERROR); 815 return shouldDispatchJavaScriptWindowOnErrorEvents; 816} 817 818static bool isInternalInstall() 819{ 820 static bool isInternal = MGGetBoolAnswer(kMGQAppleInternalInstallCapability); 821 return isInternal; 822} 823 824static bool didOneTimeInitialization = false; 825#endif 826 827static bool shouldUseLegacyBackgroundSizeShorthandBehavior() 828{ 829#if PLATFORM(IOS) 830 static bool shouldUseLegacyBackgroundSizeShorthandBehavior = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_LEGACY_BACKGROUNDSIZE_SHORTHAND_BEHAVIOR); 831#else 832 static bool shouldUseLegacyBackgroundSizeShorthandBehavior = applicationIsVersions() 833 && !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_LEGACY_BACKGROUNDSIZE_SHORTHAND_BEHAVIOR); 834#endif 835 return shouldUseLegacyBackgroundSizeShorthandBehavior; 836} 837 838#if ENABLE(GAMEPAD) 839static void WebKitInitializeGamepadProviderIfNecessary() 840{ 841 static bool initialized = false; 842 if (initialized) 843 return; 844 845 GamepadProvider::shared().setSharedProvider(HIDGamepadProvider::shared()); 846 initialized = true; 847} 848#endif 849 850- (void)_commonInitializationWithFrameName:(NSString *)frameName groupName:(NSString *)groupName 851{ 852 WebCoreThreadViolationCheckRoundTwo(); 853 854#ifndef NDEBUG 855 WTF::RefCountedLeakCounter::suppressMessages(webViewIsOpen); 856#endif 857 858 WebPreferences *standardPreferences = [WebPreferences standardPreferences]; 859 [standardPreferences willAddToWebView]; 860 861 _private->preferences = [standardPreferences retain]; 862 _private->mainFrameDocumentReady = NO; 863 _private->drawsBackground = YES; 864#if !PLATFORM(IOS) 865 _private->backgroundColor = [[NSColor colorWithDeviceWhite:1 alpha:1] retain]; 866#else 867 _private->backgroundColor = CGColorRetain(cachedCGColor(Color::white, ColorSpaceDeviceRGB)); 868#endif 869 _private->includesFlattenedCompositingLayersWhenDrawingToBitmap = YES; 870 871 NSRect f = [self frame]; 872 WebFrameView *frameView = [[WebFrameView alloc] initWithFrame: NSMakeRect(0,0,f.size.width,f.size.height)]; 873 [frameView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; 874 [self addSubview:frameView]; 875 [frameView release]; 876 877#if !PLATFORM(IOS) 878 static bool didOneTimeInitialization = false; 879#endif 880 if (!didOneTimeInitialization) { 881#if !LOG_DISABLED 882 WebKitInitializeLoggingChannelsIfNecessary(); 883 WebCore::initializeLoggingChannelsIfNecessary(); 884#endif // !LOG_DISABLED 885 886 // Initialize our platform strategies first before invoking the rest 887 // of the initialization code which may depend on the strategies. 888 WebPlatformStrategies::initializeIfNecessary(); 889 890#if ENABLE(SQL_DATABASE) 891#if PLATFORM(IOS) 892 // Set the WebSQLiteDatabaseTrackerClient. 893 SQLiteDatabaseTracker::setClient(WebSQLiteDatabaseTrackerClient::sharedWebSQLiteDatabaseTrackerClient()); 894 895 if ([standardPreferences databasesEnabled]) 896#endif 897 [WebDatabaseManager sharedWebDatabaseManager]; 898#endif 899 900#if PLATFORM(IOS) 901 if ([standardPreferences storageTrackerEnabled]) 902#endif 903 WebKitInitializeStorageIfNecessary(); 904 WebKitInitializeApplicationCachePathIfNecessary(); 905#if ENABLE(DISK_IMAGE_CACHE) && PLATFORM(IOS) 906 WebKitInitializeWebDiskImageCache(); 907#endif 908#if ENABLE(GAMEPAD) 909 WebKitInitializeGamepadProviderIfNecessary(); 910#endif 911 912 Settings::setDefaultMinDOMTimerInterval(0.004); 913 914 Settings::setShouldRespectPriorityInCSSAttributeSetters(shouldRespectPriorityInCSSAttributeSetters()); 915 916#if PLATFORM(IOS) 917 if (applicationIsMobileSafari()) 918 Settings::setShouldManageAudioSessionCategory(true); 919#endif 920 921 didOneTimeInitialization = true; 922 } 923 924 Page::PageClients pageClients; 925#if !PLATFORM(IOS) 926 pageClients.chromeClient = new WebChromeClient(self); 927 pageClients.contextMenuClient = new WebContextMenuClient(self); 928#if ENABLE(DRAG_SUPPORT) 929 pageClients.dragClient = new WebDragClient(self); 930#endif 931 pageClients.inspectorClient = new WebInspectorClient(self); 932#else 933 pageClients.chromeClient = new WebChromeClientIOS(self); 934 pageClients.inspectorClient = new WebInspectorClient(self); 935#endif 936 pageClients.editorClient = new WebEditorClient(self); 937 pageClients.alternativeTextClient = new WebAlternativeTextClient(self); 938 pageClients.loaderClientForMainFrame = new WebFrameLoaderClient; 939 pageClients.progressTrackerClient = new WebProgressTrackerClient(self); 940 _private->page = new Page(pageClients); 941#if ENABLE(GEOLOCATION) 942 WebCore::provideGeolocationTo(_private->page, new WebGeolocationClient(self)); 943#endif 944#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS) 945 WebCore::provideNotification(_private->page, new WebNotificationClient(self)); 946#endif 947#if ENABLE(DEVICE_ORIENTATION) 948#if !PLATFORM(IOS) 949 WebCore::provideDeviceOrientationTo(_private->page, new WebDeviceOrientationClient(self)); 950#endif 951#endif 952#if ENABLE(MEDIA_STREAM) 953 WebCore::provideUserMediaTo(_private->page, new WebUserMediaClient(self)); 954#endif 955 956#if ENABLE(REMOTE_INSPECTOR) 957 _private->page->setRemoteInspectionAllowed(true); 958#endif 959 960 _private->page->setCanStartMedia([self window]); 961 _private->page->settings().setLocalStorageDatabasePath([[self preferences] _localStorageDatabasePath]); 962 _private->page->settings().setUseLegacyBackgroundSizeShorthandBehavior(shouldUseLegacyBackgroundSizeShorthandBehavior()); 963 964#if !PLATFORM(IOS) 965 if (needsOutlookQuirksScript()) { 966 _private->page->settings().setShouldInjectUserScriptsInInitialEmptyDocument(true); 967 [self _injectOutlookQuirksScript]; 968 } 969#endif 970 971#if PLATFORM(IOS) 972 // Preserve the behavior we had before <rdar://problem/7580867> 973 // by enforcing a 5MB limit for session storage. 974 _private->page->settings().setSessionStorageQuota(5 * 1024 * 1024); 975 976 [self _updateScreenScaleFromWindow]; 977 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_wakWindowScreenScaleChanged:) name:WAKWindowScreenScaleDidChangeNotification object:nil]; 978 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_wakWindowVisibilityChanged:) name:WAKWindowVisibilityDidChangeNotification object:nil]; 979 _private->_fixedPositionContent = [[WebFixedPositionContent alloc] initWithWebView:self]; 980#endif 981 982 if ([[NSUserDefaults standardUserDefaults] objectForKey:WebSmartInsertDeleteEnabled]) 983 [self setSmartInsertDeleteEnabled:[[NSUserDefaults standardUserDefaults] boolForKey:WebSmartInsertDeleteEnabled]]; 984 985 [WebFrame _createMainFrameWithPage:_private->page frameName:frameName frameView:frameView]; 986 987#if !PLATFORM(IOS) 988 NSRunLoop *runLoop = [NSRunLoop mainRunLoop]; 989 990 if (WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_LOADING_DURING_COMMON_RUNLOOP_MODES)) 991 [self scheduleInRunLoop:runLoop forMode:(NSString *)kCFRunLoopCommonModes]; 992 else 993 [self scheduleInRunLoop:runLoop forMode:NSDefaultRunLoopMode]; 994#endif 995 996 [self _addToAllWebViewsSet]; 997 [self setGroupName:groupName]; 998 999 // If there's already a next key view (e.g., from a nib), wire it up to our 1000 // contained frame view. In any case, wire our next key view up to the our 1001 // contained frame view. This works together with our becomeFirstResponder 1002 // and setNextKeyView overrides. 1003 NSView *nextKeyView = [self nextKeyView]; 1004 if (nextKeyView && nextKeyView != frameView) 1005 [frameView setNextKeyView:nextKeyView]; 1006 [super setNextKeyView:frameView]; 1007 1008 if ([[self class] shouldIncludeInWebKitStatistics]) 1009 ++WebViewCount; 1010 1011#if !PLATFORM(IOS) 1012 [self _registerDraggedTypes]; 1013#endif 1014 1015 [self _setIsVisible:[self _isViewVisible]]; 1016 1017 WebPreferences *prefs = [self preferences]; 1018 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:) 1019 name:WebPreferencesChangedInternalNotification object:prefs]; 1020 1021#if !PLATFORM(IOS) 1022 [self _preferencesChanged:[self preferences]]; 1023 [[self preferences] _postPreferencesChangedAPINotification]; 1024#else 1025 // do this on the current thread on iOS, since the web thread could be blocked on the main thread, 1026 // and prefs need to be changed synchronously <rdar://problem/5841558> 1027 [self _preferencesChanged:prefs]; 1028 _private->page->settings().setFontFallbackPrefersPictographs(true); 1029#endif 1030 1031 memoryPressureHandler().install(); 1032 1033 if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_LOCAL_RESOURCE_SECURITY_RESTRICTION)) { 1034 // Originally, we allowed all local loads. 1035 SecurityPolicy::setLocalLoadPolicy(SecurityPolicy::AllowLocalLoadsForAll); 1036 } else if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_MORE_STRICT_LOCAL_RESOURCE_SECURITY_RESTRICTION)) { 1037 // Later, we allowed local loads for local URLs and documents loaded 1038 // with substitute data. 1039 SecurityPolicy::setLocalLoadPolicy(SecurityPolicy::AllowLocalLoadsForLocalAndSubstituteData); 1040 } 1041 1042#if !PLATFORM(IOS) 1043 if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_CONTENT_SNIFFING_FOR_FILE_URLS)) 1044 ResourceHandle::forceContentSniffing(); 1045#endif 1046 1047#if USE(GLIB) 1048 [self _scheduleGlibContextIterations]; 1049#endif 1050} 1051 1052- (id)_initWithFrame:(NSRect)f frameName:(NSString *)frameName groupName:(NSString *)groupName 1053{ 1054 self = [super initWithFrame:f]; 1055 if (!self) 1056 return nil; 1057 1058#ifdef ENABLE_WEBKIT_UNSET_DYLD_FRAMEWORK_PATH 1059 // DYLD_FRAMEWORK_PATH is used so Safari will load the development version of WebKit, which 1060 // may not work with other WebKit applications. Unsetting DYLD_FRAMEWORK_PATH removes the 1061 // need for Safari to unset it to prevent it from being passed to applications it launches. 1062 // Unsetting it when a WebView is first created is as good a place as any. 1063 // See <http://bugs.webkit.org/show_bug.cgi?id=4286> for more details. 1064 if (getenv("WEBKIT_UNSET_DYLD_FRAMEWORK_PATH")) { 1065 unsetenv("DYLD_FRAMEWORK_PATH"); 1066 unsetenv("WEBKIT_UNSET_DYLD_FRAMEWORK_PATH"); 1067 } 1068#endif 1069 1070 _private = [[WebViewPrivate alloc] init]; 1071 [self _commonInitializationWithFrameName:frameName groupName:groupName]; 1072 [self setMaintainsBackForwardList: YES]; 1073#if !PLATFORM(IOS) 1074 _private->page->setDeviceScaleFactor([self _deviceScaleFactor]); 1075#endif 1076 return self; 1077} 1078 1079- (void)_viewWillDrawInternal 1080{ 1081 Frame* frame = [self _mainCoreFrame]; 1082 if (frame && frame->view()) 1083 frame->view()->updateLayoutAndStyleIfNeededRecursive(); 1084} 1085 1086+ (NSArray *)_supportedMIMETypes 1087{ 1088 // Load the plug-in DB allowing plug-ins to install types. 1089 [WebPluginDatabase sharedDatabase]; 1090 return [[WebFrameView _viewTypesAllowImageTypeOmission:NO] allKeys]; 1091} 1092 1093#if !PLATFORM(IOS) 1094+ (NSArray *)_supportedFileExtensions 1095{ 1096 NSMutableSet *extensions = [[NSMutableSet alloc] init]; 1097 NSArray *MIMETypes = [self _supportedMIMETypes]; 1098 NSEnumerator *enumerator = [MIMETypes objectEnumerator]; 1099 NSString *MIMEType; 1100 while ((MIMEType = [enumerator nextObject]) != nil) { 1101 NSArray *extensionsForType = WKGetExtensionsForMIMEType(MIMEType); 1102 if (extensionsForType) { 1103 [extensions addObjectsFromArray:extensionsForType]; 1104 } 1105 } 1106 NSArray *uniqueExtensions = [extensions allObjects]; 1107 [extensions release]; 1108 return uniqueExtensions; 1109} 1110#endif 1111 1112#if PLATFORM(IOS) 1113+ (void)enableWebThread 1114{ 1115 static BOOL isWebThreadEnabled = NO; 1116 if (!isWebThreadEnabled) { 1117 WebCoreObjCDeallocOnWebThread([WebBasePluginPackage class]); 1118 WebCoreObjCDeallocOnWebThread([WebDataSource class]); 1119 WebCoreObjCDeallocOnWebThread([WebFrame class]); 1120 WebCoreObjCDeallocOnWebThread([WebHTMLView class]); 1121 WebCoreObjCDeallocOnWebThread([WebHistoryItem class]); 1122 WebCoreObjCDeallocOnWebThread([WebPlainWhiteView class]); 1123 WebCoreObjCDeallocOnWebThread([WebPolicyDecisionListener class]); 1124 WebCoreObjCDeallocOnWebThread([WebView class]); 1125 WebCoreObjCDeallocOnWebThread([WebVisiblePosition class]); 1126 if (applicationIsTheEconomistOnIPhone() && !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_DELEGATE_CALLS_IN_COMMON_RUNLOOP_MODES)) 1127 WebThreadSetDelegateSourceRunLoopMode(kCFRunLoopDefaultMode); 1128 WebThreadEnable(); 1129 isWebThreadEnabled = YES; 1130 } 1131} 1132 1133- (id)initSimpleHTMLDocumentWithStyle:(NSString *)style frame:(CGRect)frame preferences:(WebPreferences *)preferences groupName:(NSString *)groupName 1134{ 1135 self = [super initWithFrame:frame]; 1136 if (!self) 1137 return nil; 1138 1139 _private = [[WebViewPrivate alloc] init]; 1140 1141#ifndef NDEBUG 1142 WTF::RefCountedLeakCounter::suppressMessages(webViewIsOpen); 1143#endif 1144 1145 if (!preferences) 1146 preferences = [WebPreferences standardPreferences]; 1147 [preferences willAddToWebView]; 1148 1149 _private->preferences = [preferences retain]; 1150 _private->mainFrameDocumentReady = NO; 1151 _private->drawsBackground = YES; 1152 _private->backgroundColor = CGColorRetain(cachedCGColor(Color::white, ColorSpaceDeviceRGB)); 1153 1154 WebFrameView *frameView = nil; 1155 frameView = [[WebFrameView alloc] initWithFrame: CGRectMake(0,0,frame.size.width,frame.size.height)]; 1156 [frameView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; 1157 [self addSubview:frameView]; 1158 [frameView release]; 1159 1160 1161 Page::PageClients pageClients; 1162 pageClients.chromeClient = new WebChromeClientIOS(self); 1163#if ENABLE(DRAG_SUPPORT) 1164 pageClients.dragClient = new WebDragClient(self); 1165#endif 1166 pageClients.editorClient = new WebEditorClient(self); 1167 pageClients.inspectorClient = new WebInspectorClient(self); 1168 pageClients.loaderClientForMainFrame = new WebFrameLoaderClient; 1169 pageClients.progressTrackerClient = new WebProgressTrackerClient(self); 1170 _private->page = new Page(pageClients); 1171 1172 [self setSmartInsertDeleteEnabled:YES]; 1173 1174 // FIXME: <rdar://problem/6851451> Should respect preferences in fast path WebView initialization 1175 // We are ignoring the preferences object on fast path and just using Settings defaults (everything fancy off). 1176 // This matches how UIKit sets up the preferences. We need to set default values for fonts though, <rdar://problem/6850611>. 1177 // This should be revisited later. There is some risk involved, _preferencesChanged used to show up badly in Shark. 1178 _private->page->settings().setMinimumLogicalFontSize(9); 1179 _private->page->settings().setDefaultFontSize([_private->preferences defaultFontSize]); 1180 _private->page->settings().setDefaultFixedFontSize(13); 1181 _private->page->settings().setDownloadableBinaryFontsEnabled(false); 1182 _private->page->settings().setAcceleratedDrawingEnabled([preferences acceleratedDrawingEnabled]); 1183 _private->page->settings().setScreenFontSubstitutionEnabled(false); 1184 1185 // FIXME: <rdar://problem/7394370> Always use primary font baseline in text field base line calculation, ignore fallback fonts. 1186 _private->page->settings().setAlwaysUseBaselineOfPrimaryFont([preferences _alwaysUseBaselineOfPrimaryFont]); 1187 1188 _private->page->settings().setFontFallbackPrefersPictographs(true); 1189 _private->page->settings().setPictographFontFamily("AppleColorEmoji"); 1190 1191 // FIXME: this is a workaround for <rdar://problem/11518688> REGRESSION: Quoted text font changes when replying to certain email 1192 _private->page->settings().setStandardFontFamily([_private->preferences standardFontFamily]); 1193 1194 // FIXME: this is a workaround for <rdar://problem/11820090> Quoted text changes in size when replying to certain email 1195 _private->page->settings().setMinimumFontSize([_private->preferences minimumFontSize]); 1196 1197 [self setGroupName:groupName]; 1198 1199#if ENABLE(REMOTE_INSPECTOR) 1200 _private->page->setRemoteInspectionAllowed(isInternalInstall()); 1201#endif 1202 1203 [self _updateScreenScaleFromWindow]; 1204 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_wakWindowScreenScaleChanged:) name:WAKWindowScreenScaleDidChangeNotification object:nil]; 1205 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_wakWindowVisibilityChanged:) name:WAKWindowVisibilityDidChangeNotification object:nil]; 1206 1207 [WebFrame _createMainFrameWithSimpleHTMLDocumentWithPage:_private->page frameView:frameView style:style]; 1208 1209 [self _addToAllWebViewsSet]; 1210 1211 ++WebViewCount; 1212 1213 SecurityPolicy::setLocalLoadPolicy(SecurityPolicy::AllowLocalLoadsForLocalAndSubstituteData); 1214 1215 return self; 1216} 1217 1218+ (void)_handleMemoryWarning 1219{ 1220 ASSERT(WebThreadIsCurrent()); 1221 WebKit::MemoryMeasure totalMemory("Memory warning: Overall memory change from [WebView _handleMemoryWarning]."); 1222 1223 // Always peform the following. 1224 [WebView purgeInactiveFontData]; 1225 1226 // Only perform the remaining if a non-simple document was created. 1227 if (!didOneTimeInitialization) 1228 return; 1229 1230 tileControllerMemoryHandler().trimUnparentedTilesToTarget(0); 1231 1232#if ENABLE(DISK_IMAGE_CACHE) 1233 { 1234 WebKit::MemoryMeasure measurer("Memory warning: flushing images to disk."); 1235 WebCore::memoryCache()->flushCachedImagesToDisk(); 1236 } 1237#endif 1238 1239 [WebStorageManager closeIdleLocalStorageDatabases]; 1240 1241 [WebView _releaseMemoryNow]; 1242} 1243 1244+ (void)registerForMemoryNotifications 1245{ 1246 BOOL shouldAutoClearPressureOnMemoryRelease = !WebCore::applicationIsMobileSafari(); 1247 1248 memoryPressureHandler().installMemoryReleaseBlock(^{ 1249 [WebView _handleMemoryWarning]; 1250 }, shouldAutoClearPressureOnMemoryRelease); 1251 1252#if PLATFORM(IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 1253 static dispatch_source_t memoryNotificationEventSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_MEMORYSTATUS, 0, DISPATCH_MEMORYSTATUS_PRESSURE_WARN, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)); 1254#else 1255 static dispatch_source_t memoryNotificationEventSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_VM, 0, DISPATCH_VM_PRESSURE, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)); 1256#endif 1257 dispatch_source_set_event_handler(memoryNotificationEventSource, ^{ 1258 // Set memory pressure flag and schedule releasing memory in web thread runloop exit. 1259 memoryPressureHandler().setReceivedMemoryPressure(WebCore::MemoryPressureReasonVMPressure); 1260 }); 1261 1262 dispatch_resume(memoryNotificationEventSource); 1263 1264 if (!shouldAutoClearPressureOnMemoryRelease) { 1265 // Listen to memory status notification to reset the memory pressure flag. 1266 static dispatch_source_t memoryStatusEventSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_MEMORYSTATUS, 1267 0, 1268 DISPATCH_MEMORYSTATUS_PRESSURE_WARN | DISPATCH_MEMORYSTATUS_PRESSURE_NORMAL, 1269 dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)); 1270 dispatch_source_set_event_handler(memoryStatusEventSource, ^{ 1271 unsigned long currentStatus = dispatch_source_get_data(memoryStatusEventSource); 1272 if (currentStatus == DISPATCH_MEMORYSTATUS_PRESSURE_NORMAL) 1273 memoryPressureHandler().clearMemoryPressure(); 1274 else if (currentStatus == DISPATCH_MEMORYSTATUS_PRESSURE_WARN) 1275 memoryPressureHandler().setReceivedMemoryPressure(WebCore::MemoryPressureReasonVMStatus); 1276 }); 1277 1278 dispatch_resume(memoryStatusEventSource); 1279 } 1280} 1281 1282+ (void)_releaseMemoryNow 1283{ 1284 ASSERT(WebThreadIsCurrent()); 1285 [WebView discardAllCompiledCode]; 1286 [WebView garbageCollectNow]; 1287 [WebView purgeInactiveFontData]; 1288 [WebView drainLayerPool]; 1289 [WebCache emptyInMemoryResources]; 1290 [WebView releaseFastMallocMemoryOnCurrentThread]; 1291 1292 dispatch_async(dispatch_get_main_queue(), ^{ 1293 // Clear the main thread's TCMalloc thread cache. 1294 [WebView releaseFastMallocMemoryOnCurrentThread]; 1295 }); 1296} 1297 1298+ (void)_clearPrivateBrowsingSessionCookieStorage 1299{ 1300 WebFrameNetworkingContext::clearPrivateBrowsingSessionCookieStorage(); 1301} 1302 1303- (void)_replaceCurrentHistoryItem:(WebHistoryItem *)item 1304{ 1305 Frame* frame = [self _mainCoreFrame]; 1306 if (frame) 1307 frame->loader().history().replaceCurrentItem(core(item)); 1308} 1309 1310+ (void)willEnterBackgroundWithCompletionHandler:(void(^)(void))handler 1311{ 1312 WebThreadRun(^{ 1313 [WebView _releaseMemoryNow]; 1314 dispatch_async(dispatch_get_main_queue(), handler); 1315 }); 1316} 1317 1318+ (void)releaseFastMallocMemoryOnCurrentThread 1319{ 1320 WebKit::MemoryMeasure measurer("Memory warning: Releasing fast malloc memory to system."); 1321 WTF::releaseFastMallocFreeMemory(); 1322} 1323 1324+ (void)garbageCollectNow 1325{ 1326 ASSERT(WebThreadIsCurrent()); 1327 WebKit::MemoryMeasure measurer("Memory warning: Calling JavaScript GC."); 1328 gcController().garbageCollectNow(); 1329} 1330 1331+ (void)purgeInactiveFontData 1332{ 1333 ASSERT(WebThreadIsCurrent()); 1334 WebKit::MemoryMeasure measurer("Memory warning: Purging inactive font data."); 1335 fontCache().purgeInactiveFontData(); 1336} 1337 1338+ (void)drainLayerPool 1339{ 1340 ASSERT(WebThreadIsCurrent()); 1341 WebKit::MemoryMeasure measurer("Memory warning: Draining layer pool."); 1342 WebCore::LegacyTileCache::drainLayerPool(); 1343} 1344 1345+ (void)discardAllCompiledCode 1346{ 1347 ASSERT(WebThreadIsCurrent()); 1348 WebKit::MemoryMeasure measurer("Memory warning: Discarding JIT'ed code."); 1349 gcController().discardAllCompiledCode(); 1350} 1351 1352+ (BOOL)isCharacterSmartReplaceExempt:(unichar)character isPreviousCharacter:(BOOL)b 1353{ 1354 return WebCore::isCharacterSmartReplaceExempt(character, b); 1355} 1356 1357- (void)updateLayoutIgnorePendingStyleSheets 1358{ 1359 WebThreadRun(^{ 1360 for (Frame* frame = [self _mainCoreFrame]; frame; frame = frame->tree().traverseNext()) { 1361 Document *document = frame->document(); 1362 if (document) 1363 document->updateLayoutIgnorePendingStylesheets(); 1364 } 1365 }); 1366} 1367#endif // PLATFORM(IOS) 1368 1369static NSMutableSet *knownPluginMIMETypes() 1370{ 1371 static NSMutableSet *mimeTypes = [[NSMutableSet alloc] init]; 1372 1373 return mimeTypes; 1374} 1375 1376+ (void)_registerPluginMIMEType:(NSString *)MIMEType 1377{ 1378 [WebView registerViewClass:[WebHTMLView class] representationClass:[WebHTMLRepresentation class] forMIMEType:MIMEType]; 1379 [knownPluginMIMETypes() addObject:MIMEType]; 1380} 1381 1382+ (void)_unregisterPluginMIMEType:(NSString *)MIMEType 1383{ 1384 [self _unregisterViewClassAndRepresentationClassForMIMEType:MIMEType]; 1385 [knownPluginMIMETypes() removeObject:MIMEType]; 1386} 1387 1388+ (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType allowingPlugins:(BOOL)allowPlugins 1389{ 1390 MIMEType = [MIMEType lowercaseString]; 1391 Class viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:YES] _webkit_objectForMIMEType:MIMEType]; 1392 Class repClass = [[WebDataSource _repTypesAllowImageTypeOmission:YES] _webkit_objectForMIMEType:MIMEType]; 1393 1394#if PLATFORM(IOS) 1395#define WebPDFView ([WebView _getPDFViewClass]) 1396#endif 1397 if (!viewClass || !repClass || [[WebPDFView supportedMIMETypes] containsObject:MIMEType]) { 1398#if PLATFORM(IOS) 1399#undef WebPDFView 1400#endif 1401 // Our optimization to avoid loading the plug-in DB and image types for the HTML case failed. 1402 1403 if (allowPlugins) { 1404 // Load the plug-in DB allowing plug-ins to install types. 1405 [WebPluginDatabase sharedDatabase]; 1406 } 1407 1408 // Load the image types and get the view class and rep class. This should be the fullest picture of all handled types. 1409 viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:NO] _webkit_objectForMIMEType:MIMEType]; 1410 repClass = [[WebDataSource _repTypesAllowImageTypeOmission:NO] _webkit_objectForMIMEType:MIMEType]; 1411 } 1412 1413 if (viewClass && repClass) { 1414 if (viewClass == [WebHTMLView class] && repClass == [WebHTMLRepresentation class]) { 1415 // Special-case WebHTMLView for text types that shouldn't be shown. 1416 if ([[WebHTMLView unsupportedTextMIMETypes] containsObject:MIMEType]) 1417 return NO; 1418 1419 // If the MIME type is a known plug-in we might not want to load it. 1420 if (!allowPlugins && [knownPluginMIMETypes() containsObject:MIMEType]) { 1421 BOOL isSupportedByWebKit = [[WebHTMLView supportedNonImageMIMETypes] containsObject:MIMEType] || 1422 [[WebHTMLView supportedMIMETypes] containsObject:MIMEType]; 1423 1424 // If this is a known plug-in MIME type and WebKit can't show it natively, we don't want to show it. 1425 if (!isSupportedByWebKit) 1426 return NO; 1427 } 1428 } 1429 if (vClass) 1430 *vClass = viewClass; 1431 if (rClass) 1432 *rClass = repClass; 1433 return YES; 1434 } 1435 1436 return NO; 1437} 1438 1439- (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType 1440{ 1441 if ([[self class] _viewClass:vClass andRepresentationClass:rClass forMIMEType:MIMEType allowingPlugins:[_private->preferences arePlugInsEnabled]]) 1442 return YES; 1443#if !PLATFORM(IOS) 1444 if (_private->pluginDatabase) { 1445 WebBasePluginPackage *pluginPackage = [_private->pluginDatabase pluginForMIMEType:MIMEType]; 1446 if (pluginPackage) { 1447 if (vClass) 1448 *vClass = [WebHTMLView class]; 1449 if (rClass) 1450 *rClass = [WebHTMLRepresentation class]; 1451 return YES; 1452 } 1453 } 1454#endif 1455 return NO; 1456} 1457 1458+ (void)_setAlwaysUsesComplexTextCodePath:(BOOL)f 1459{ 1460 Font::setCodePath(f ? Font::Complex : Font::Auto); 1461} 1462 1463+ (void)_setAllowsRoundingHacks:(BOOL)allowsRoundingHacks 1464{ 1465 TextRun::setAllowsRoundingHacks(allowsRoundingHacks); 1466} 1467 1468+ (BOOL)_allowsRoundingHacks 1469{ 1470 return TextRun::allowsRoundingHacks(); 1471} 1472 1473+ (BOOL)canCloseAllWebViews 1474{ 1475 return DOMWindow::dispatchAllPendingBeforeUnloadEvents(); 1476} 1477 1478+ (void)closeAllWebViews 1479{ 1480 DOMWindow::dispatchAllPendingUnloadEvents(); 1481 1482 // This will close the WebViews in a random order. Change this if close order is important. 1483 // Make a new set to avoid mutating the set we are enumerating. 1484 NSSet *webViewsToClose = [NSSet setWithSet:(NSSet *)allWebViewsSet]; 1485 NSEnumerator *enumerator = [webViewsToClose objectEnumerator]; 1486 while (WebView *webView = [enumerator nextObject]) 1487 [webView close]; 1488} 1489 1490+ (BOOL)canShowFile:(NSString *)path 1491{ 1492 return [[self class] canShowMIMEType:[WebView _MIMETypeForFile:path]]; 1493} 1494 1495#if !PLATFORM(IOS) 1496+ (NSString *)suggestedFileExtensionForMIMEType:(NSString *)type 1497{ 1498 return WKGetPreferredExtensionForMIMEType(type); 1499} 1500#endif 1501 1502- (BOOL)_isClosed 1503{ 1504 return !_private || _private->closed; 1505} 1506 1507#if PLATFORM(IOS) 1508- (void)_dispatchUnloadEvent 1509{ 1510 WebThreadRun(^{ 1511 WebFrame *mainFrame = [self mainFrame]; 1512 Frame *coreMainFrame = core(mainFrame); 1513 if (coreMainFrame) { 1514 Document *document = coreMainFrame->document(); 1515 if (document) 1516 document->dispatchWindowEvent(Event::create(eventNames().unloadEvent, false, false)); 1517 } 1518 }); 1519} 1520 1521- (DOMCSSStyleDeclaration *)styleAtSelectionStart 1522{ 1523 WebFrame *mainFrame = [self mainFrame]; 1524 Frame *coreMainFrame = core(mainFrame); 1525 if (!coreMainFrame) 1526 return nil; 1527 return coreMainFrame->styleAtSelectionStart(); 1528} 1529 1530- (NSUInteger)_renderTreeSize 1531{ 1532 if (!_private->page) 1533 return 0; 1534 return _private->page->renderTreeSize(); 1535} 1536 1537- (void)_dispatchTileDidDraw:(CALayer*)tile 1538{ 1539 id mailDelegate = [self _webMailDelegate]; 1540 if ([mailDelegate respondsToSelector:@selector(_webthread_webView:tileDidDraw:)]) { 1541 [mailDelegate _webthread_webView:self tileDidDraw:tile]; 1542 return; 1543 } 1544 1545 if (!OSAtomicCompareAndSwap32(0, 1, &_private->didDrawTiles)) 1546 return; 1547 1548 WebThreadLock(); 1549 1550 [[[self _UIKitDelegateForwarder] asyncForwarder] webViewDidDrawTiles:self]; 1551} 1552 1553- (void)_willStartScrollingOrZooming 1554{ 1555 // Pause timers during top level interaction 1556 if (_private->mainViewIsScrollingOrZooming) 1557 return; 1558 _private->mainViewIsScrollingOrZooming = YES; 1559 1560 // This suspends active DOM objects like timers, but not media. 1561 [[self mainFrame] setTimeoutsPaused:YES]; 1562 1563 // This defers loading callbacks only. 1564 // WARNING: This behavior could change if Bug 49401 lands in open source WebKit again. 1565 [self setDefersCallbacks:YES]; 1566} 1567 1568- (void)_didFinishScrollingOrZooming 1569{ 1570 if (!_private->mainViewIsScrollingOrZooming) 1571 return; 1572 _private->mainViewIsScrollingOrZooming = NO; 1573 [self setDefersCallbacks:NO]; 1574 [[self mainFrame] setTimeoutsPaused:NO]; 1575 if (FrameView* view = [self _mainCoreFrame]->view()) 1576 view->resumeVisibleImageAnimationsIncludingSubframes(); 1577} 1578 1579- (void)_setResourceLoadSchedulerSuspended:(BOOL)suspend 1580{ 1581 if (suspend) 1582 resourceLoadScheduler()->suspendPendingRequests(); 1583 else 1584 resourceLoadScheduler()->resumePendingRequests(); 1585} 1586 1587+ (void)_setAllowCookies:(BOOL)allow 1588{ 1589 ResourceRequestBase::setDefaultAllowCookies(allow); 1590} 1591 1592+ (BOOL)_allowCookies 1593{ 1594 return ResourceRequestBase::defaultAllowCookies(); 1595} 1596 1597+ (BOOL)_isUnderMemoryPressure 1598{ 1599 return memoryPressureHandler().isUnderMemoryPressure(); 1600} 1601 1602+ (void)_clearMemoryPressure 1603{ 1604 memoryPressureHandler().clearMemoryPressure(); 1605} 1606 1607+ (BOOL)_shouldWaitForMemoryClearMessage 1608{ 1609 return memoryPressureHandler().shouldWaitForMemoryClearMessage(); 1610} 1611#endif // PLATFORM(IOS) 1612 1613- (void)_closePluginDatabases 1614{ 1615 pluginDatabaseClientCount--; 1616 1617 // Close both sets of plug-in databases because plug-ins need an opportunity to clean up files, etc. 1618 1619#if !PLATFORM(IOS) 1620 // Unload the WebView local plug-in database. 1621 if (_private->pluginDatabase) { 1622 [_private->pluginDatabase destroyAllPluginInstanceViews]; 1623 [_private->pluginDatabase close]; 1624 [_private->pluginDatabase release]; 1625 _private->pluginDatabase = nil; 1626 } 1627#endif 1628 1629 // Keep the global plug-in database active until the app terminates to avoid having to reload plug-in bundles. 1630 if (!pluginDatabaseClientCount && applicationIsTerminating) 1631 [WebPluginDatabase closeSharedDatabase]; 1632} 1633 1634- (void)_closeWithFastTeardown 1635{ 1636#ifndef NDEBUG 1637 WTF::RefCountedLeakCounter::suppressMessages("At least one WebView was closed with fast teardown."); 1638#endif 1639 1640#if !PLATFORM(IOS) 1641 [[NSDistributedNotificationCenter defaultCenter] removeObserver:self]; 1642#endif 1643 [[NSNotificationCenter defaultCenter] removeObserver:self]; 1644 1645 [self _closePluginDatabases]; 1646} 1647 1648static bool fastDocumentTeardownEnabled() 1649{ 1650#ifdef NDEBUG 1651 static bool enabled = ![[NSUserDefaults standardUserDefaults] boolForKey:WebKitEnableFullDocumentTeardownPreferenceKey]; 1652#else 1653 static bool initialized = false; 1654 static bool enabled = false; 1655 if (!initialized) { 1656 // This allows debug builds to default to not have fast teardown, so leak checking still works. 1657 // But still allow the WebKitEnableFullDocumentTeardown default to override it if present. 1658 NSNumber *setting = [[NSUserDefaults standardUserDefaults] objectForKey:WebKitEnableFullDocumentTeardownPreferenceKey]; 1659 if (setting) 1660 enabled = ![setting boolValue]; 1661 initialized = true; 1662 } 1663#endif 1664 return enabled; 1665} 1666 1667// _close is here only for backward compatibility; clients and subclasses should use 1668// public method -close instead. 1669- (void)_close 1670{ 1671#if PLATFORM(IOS) 1672 // Always clear delegates on calling thread, becasue caller can deallocate delegates right after calling -close 1673 // (and could in fact already be in delegate's -dealloc method, as seen in <rdar://problem/11540972>). 1674 1675 [self _clearDelegates]; 1676 1677 // Fix for problems such as <rdar://problem/5774587> Crash closing tab in WebCore::Frame::page() from -[WebCoreFrameBridge pauseTimeouts] 1678 WebThreadRun(^{ 1679#endif 1680 1681 if (!_private || _private->closed) 1682 return; 1683 1684 [[NSNotificationCenter defaultCenter] postNotificationName:WebViewWillCloseNotification object:self]; 1685 1686 _private->closed = YES; 1687 [self _removeFromAllWebViewsSet]; 1688 1689#ifndef NDEBUG 1690 WTF::RefCountedLeakCounter::cancelMessageSuppression(webViewIsOpen); 1691#endif 1692 1693 // To quit the apps fast we skip document teardown, except plugins 1694 // need to be destroyed and unloaded. 1695 if (applicationIsTerminating && fastDocumentTeardownEnabled()) { 1696 [self _closeWithFastTeardown]; 1697 return; 1698 } 1699 1700#if ENABLE(VIDEO) && !PLATFORM(IOS) 1701 [self _exitFullscreen]; 1702#endif 1703 1704#if PLATFORM(IOS) 1705 _private->closing = YES; 1706#endif 1707 1708 if (Frame* mainFrame = [self _mainCoreFrame]) 1709 mainFrame->loader().detachFromParent(); 1710 1711 [self setHostWindow:nil]; 1712 1713#if !PLATFORM(IOS) 1714 [self setDownloadDelegate:nil]; 1715 [self setEditingDelegate:nil]; 1716 [self setFrameLoadDelegate:nil]; 1717 [self setPolicyDelegate:nil]; 1718 [self setResourceLoadDelegate:nil]; 1719 [self setScriptDebugDelegate:nil]; 1720 [self setUIDelegate:nil]; 1721 1722 [_private->inspector webViewClosed]; 1723#endif 1724 1725#if !PLATFORM(IOS) 1726 // To avoid leaks, call removeDragCaret in case it wasn't called after moveDragCaretToPoint. 1727 [self removeDragCaret]; 1728#endif 1729 1730 _private->group->removeWebView(self); 1731 1732 // Deleteing the WebCore::Page will clear the page cache so we call destroy on 1733 // all the plug-ins in the page cache to break any retain cycles. 1734 // See comment in HistoryItem::releaseAllPendingPageCaches() for more information. 1735 Page* page = _private->page; 1736 _private->page = 0; 1737 delete page; 1738 1739#if !PLATFORM(IOS) 1740 if (_private->hasSpellCheckerDocumentTag) { 1741 [[NSSpellChecker sharedSpellChecker] closeSpellDocumentWithTag:_private->spellCheckerDocumentTag]; 1742 _private->hasSpellCheckerDocumentTag = NO; 1743 } 1744#endif 1745 1746 if (_private->layerFlushController) { 1747 _private->layerFlushController->invalidate(); 1748 _private->layerFlushController = nullptr; 1749 } 1750 1751#if USE(GLIB) 1752 [self _clearGlibLoopObserver]; 1753#endif 1754 1755 [[self _notificationProvider] unregisterWebView:self]; 1756 1757#if !PLATFORM(IOS) 1758 [[NSDistributedNotificationCenter defaultCenter] removeObserver:self]; 1759#endif 1760 [[NSNotificationCenter defaultCenter] removeObserver:self]; 1761 1762 [WebPreferences _removeReferenceForIdentifier:[self preferencesIdentifier]]; 1763 1764 WebPreferences *preferences = _private->preferences; 1765 _private->preferences = nil; 1766 [preferences didRemoveFromWebView]; 1767 [preferences release]; 1768 1769 [self _closePluginDatabases]; 1770 1771#ifndef NDEBUG 1772 // Need this to make leak messages accurate. 1773 if (applicationIsTerminating) { 1774 gcController().garbageCollectNow(); 1775 [WebCache setDisabled:YES]; 1776 } 1777#endif 1778#if PLATFORM(IOS) 1779 // Fix for problems such as <rdar://problem/5774587> Crash closing tab in WebCore::Frame::page() from -[WebCoreFrameBridge pauseTimeouts] 1780 }); 1781#endif 1782} 1783 1784// Indicates if the WebView is in the midst of a user gesture. 1785- (BOOL)_isProcessingUserGesture 1786{ 1787 return ScriptController::processingUserGesture(); 1788} 1789 1790+ (NSString *)_MIMETypeForFile:(NSString *)path 1791{ 1792#if !PLATFORM(IOS) 1793 NSString *extension = [path pathExtension]; 1794#endif 1795 NSString *MIMEType = nil; 1796 1797#if !PLATFORM(IOS) 1798 // Get the MIME type from the extension. 1799 if ([extension length] != 0) { 1800 MIMEType = WKGetMIMETypeForExtension(extension); 1801 } 1802#endif 1803 1804 // If we can't get a known MIME type from the extension, sniff. 1805 if ([MIMEType length] == 0 || [MIMEType isEqualToString:@"application/octet-stream"]) { 1806 NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:path]; 1807 NSData *data = [handle readDataOfLength:WEB_GUESS_MIME_TYPE_PEEK_LENGTH]; 1808 [handle closeFile]; 1809 if ([data length] != 0) { 1810 MIMEType = [data _webkit_guessedMIMEType]; 1811 } 1812 if ([MIMEType length] == 0) { 1813 MIMEType = @"application/octet-stream"; 1814 } 1815 } 1816 1817 return MIMEType; 1818} 1819 1820- (WebDownload *)_downloadURL:(NSURL *)URL 1821{ 1822 ASSERT(URL); 1823 1824 NSURLRequest *request = [[NSURLRequest alloc] initWithURL:URL]; 1825 WebDownload *download = [WebDownload _downloadWithRequest:request 1826 delegate:_private->downloadDelegate 1827 directory:nil]; 1828 [request release]; 1829 1830 return download; 1831} 1832 1833- (WebView *)_openNewWindowWithRequest:(NSURLRequest *)request 1834{ 1835 NSDictionary *features = [[NSDictionary alloc] init]; 1836 WebView *newWindowWebView = [[self _UIDelegateForwarder] webView:self 1837 createWebViewWithRequest:nil 1838 windowFeatures:features]; 1839 [features release]; 1840 if (!newWindowWebView) 1841 return nil; 1842 1843 CallUIDelegate(newWindowWebView, @selector(webViewShow:)); 1844 return newWindowWebView; 1845} 1846 1847- (WebInspector *)inspector 1848{ 1849 if (!_private->inspector) 1850 _private->inspector = [[WebInspector alloc] initWithWebView:self]; 1851 return _private->inspector; 1852} 1853 1854#if ENABLE(REMOTE_INSPECTOR) 1855+ (void)_enableRemoteInspector 1856{ 1857 RemoteInspector::shared().start(); 1858} 1859 1860+ (void)_disableRemoteInspector 1861{ 1862 RemoteInspector::shared().stop(); 1863} 1864 1865+ (void)_disableAutoStartRemoteInspector 1866{ 1867 RemoteInspector::startDisabled(); 1868} 1869 1870+ (BOOL)_isRemoteInspectorEnabled 1871{ 1872 return RemoteInspector::shared().enabled(); 1873} 1874 1875+ (BOOL)_hasRemoteInspectorSession 1876{ 1877 return RemoteInspector::shared().hasActiveDebugSession(); 1878} 1879 1880- (BOOL)allowsRemoteInspection 1881{ 1882 return _private->page->remoteInspectionAllowed(); 1883} 1884 1885- (void)setAllowsRemoteInspection:(BOOL)allow 1886{ 1887 _private->page->setRemoteInspectionAllowed(allow); 1888} 1889 1890- (void)setShowingInspectorIndication:(BOOL)showing 1891{ 1892#if PLATFORM(IOS) 1893 ASSERT(WebThreadIsLocked()); 1894 1895 if (showing) { 1896 if (!_private->indicateLayer) { 1897 _private->indicateLayer = [[WebIndicateLayer alloc] initWithWebView:self]; 1898 [_private->indicateLayer setNeedsLayout]; 1899 [[[self window] hostLayer] addSublayer:_private->indicateLayer]; 1900 } 1901 } else { 1902 [_private->indicateLayer removeFromSuperlayer]; 1903 [_private->indicateLayer release]; 1904 _private->indicateLayer = nil; 1905 } 1906#else 1907 // Implemented in WebCore::InspectorOverlay. 1908#endif 1909} 1910 1911#if PLATFORM(IOS) 1912- (void)_setHostApplicationProcessIdentifier:(pid_t)pid auditToken:(audit_token_t)auditToken 1913{ 1914 RetainPtr<CFDataRef> auditData = adoptCF(CFDataCreate(nullptr, (const UInt8*)&auditToken, sizeof(auditToken))); 1915 RemoteInspector::shared().setParentProcessInformation(pid, auditData); 1916} 1917#endif // PLATFORM(IOS) 1918#endif // ENABLE(REMOTE_INSPECTOR) 1919 1920- (WebCore::Page*)page 1921{ 1922 return _private->page; 1923} 1924 1925#if !PLATFORM(IOS) 1926- (NSMenu *)_menuForElement:(NSDictionary *)element defaultItems:(NSArray *)items 1927{ 1928 NSArray *defaultMenuItems = [[WebDefaultUIDelegate sharedUIDelegate] webView:self contextMenuItemsForElement:element defaultMenuItems:items]; 1929 NSArray *menuItems = defaultMenuItems; 1930 1931 // CallUIDelegate returns nil if UIDelegate is nil or doesn't respond to the selector. So we need to check that here 1932 // to distinguish between using defaultMenuItems or the delegate really returning nil to say "no context menu". 1933 SEL selector = @selector(webView:contextMenuItemsForElement:defaultMenuItems:); 1934 if (_private->UIDelegate && [_private->UIDelegate respondsToSelector:selector]) { 1935 menuItems = CallUIDelegate(self, selector, element, defaultMenuItems); 1936 if (!menuItems) 1937 return nil; 1938 } 1939 1940 unsigned count = [menuItems count]; 1941 if (!count) 1942 return nil; 1943 1944 NSMenu *menu = [[NSMenu alloc] init]; 1945 for (unsigned i = 0; i < count; i++) 1946 [menu addItem:[menuItems objectAtIndex:i]]; 1947 1948 return [menu autorelease]; 1949} 1950#endif 1951 1952- (void)_mouseDidMoveOverElement:(NSDictionary *)dictionary modifierFlags:(NSUInteger)modifierFlags 1953{ 1954 // We originally intended to call this delegate method sometimes with a nil dictionary, but due to 1955 // a bug dating back to WebKit 1.0 this delegate was never called with nil! Unfortunately we can't 1956 // start calling this with nil since it will break Adobe Help Viewer, and possibly other clients. 1957 if (!dictionary) 1958 return; 1959 CallUIDelegate(self, @selector(webView:mouseDidMoveOverElement:modifierFlags:), dictionary, modifierFlags); 1960} 1961 1962- (void)_loadBackForwardListFromOtherView:(WebView *)otherView 1963{ 1964 if (!_private->page) 1965 return; 1966 1967 if (!otherView->_private->page) 1968 return; 1969 1970 // It turns out the right combination of behavior is done with the back/forward load 1971 // type. (See behavior matrix at the top of WebFramePrivate.) So we copy all the items 1972 // in the back forward list, and go to the current one. 1973 1974 BackForwardClient* backForwardClient = _private->page->backForward().client(); 1975 ASSERT(!backForwardClient->currentItem()); // destination list should be empty 1976 1977 BackForwardClient* otherBackForwardClient = otherView->_private->page->backForward().client(); 1978 if (!otherBackForwardClient->currentItem()) 1979 return; // empty back forward list, bail 1980 1981 HistoryItem* newItemToGoTo = 0; 1982 1983 int lastItemIndex = otherBackForwardClient->forwardListCount(); 1984 for (int i = -otherBackForwardClient->backListCount(); i <= lastItemIndex; ++i) { 1985 if (i == 0) { 1986 // If this item is showing , save away its current scroll and form state, 1987 // since that might have changed since loading and it is normally not saved 1988 // until we leave that page. 1989 otherView->_private->page->mainFrame().loader().history().saveDocumentAndScrollState(); 1990 } 1991 RefPtr<HistoryItem> newItem = otherBackForwardClient->itemAtIndex(i)->copy(); 1992 if (i == 0) 1993 newItemToGoTo = newItem.get(); 1994 backForwardClient->addItem(newItem.release()); 1995 } 1996 1997 ASSERT(newItemToGoTo); 1998 _private->page->goToItem(newItemToGoTo, FrameLoadType::IndexedBackForward); 1999} 2000 2001- (void)_setFormDelegate: (id<WebFormDelegate>)delegate 2002{ 2003 _private->formDelegate = delegate; 2004#if PLATFORM(IOS) 2005 [_private->formDelegateForwarder clearTarget]; 2006 [_private->formDelegateForwarder release]; 2007 _private->formDelegateForwarder = nil; 2008#endif 2009} 2010 2011- (id<WebFormDelegate>)_formDelegate 2012{ 2013 return _private->formDelegate; 2014} 2015 2016#if PLATFORM(IOS) 2017- (id)_formDelegateForwarder 2018{ 2019 if (_private->closing) 2020 return nil; 2021 2022 if (!_private->formDelegateForwarder) 2023 _private->formDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:[self _formDelegate] defaultTarget:[WebDefaultFormDelegate sharedFormDelegate]]; 2024 return _private->formDelegateForwarder; 2025} 2026 2027- (id)_formDelegateForSelector:(SEL)selector 2028{ 2029 id delegate = self->_private->formDelegate; 2030 if ([delegate respondsToSelector:selector]) 2031 return delegate; 2032 2033 delegate = [WebDefaultFormDelegate sharedFormDelegate]; 2034 if ([delegate respondsToSelector:selector]) 2035 return delegate; 2036 2037 return nil; 2038} 2039#endif 2040 2041#if !PLATFORM(IOS) 2042- (BOOL)_needsAdobeFrameReloadingQuirk 2043{ 2044 static BOOL needsQuirk = WKAppVersionCheckLessThan(@"com.adobe.Acrobat", -1, 9.0) 2045 || WKAppVersionCheckLessThan(@"com.adobe.Acrobat.Pro", -1, 9.0) 2046 || WKAppVersionCheckLessThan(@"com.adobe.Reader", -1, 9.0) 2047 || WKAppVersionCheckLessThan(@"com.adobe.distiller", -1, 9.0) 2048 || WKAppVersionCheckLessThan(@"com.adobe.Contribute", -1, 4.2) 2049 || WKAppVersionCheckLessThan(@"com.adobe.dreamweaver-9.0", -1, 9.1) 2050 || WKAppVersionCheckLessThan(@"com.macromedia.fireworks", -1, 9.1) 2051 || WKAppVersionCheckLessThan(@"com.adobe.InCopy", -1, 5.1) 2052 || WKAppVersionCheckLessThan(@"com.adobe.InDesign", -1, 5.1) 2053 || WKAppVersionCheckLessThan(@"com.adobe.Soundbooth", -1, 2); 2054 2055 return needsQuirk; 2056} 2057 2058- (BOOL)_needsLinkElementTextCSSQuirk 2059{ 2060 static BOOL needsQuirk = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_LINK_ELEMENT_TEXT_CSS_QUIRK) 2061 && WKAppVersionCheckLessThan(@"com.e-frontier.shade10", -1, 10.6); 2062 return needsQuirk; 2063} 2064 2065- (BOOL)_needsIsLoadingInAPISenseQuirk 2066{ 2067 static BOOL needsQuirk = WKAppVersionCheckLessThan(@"com.apple.iAdProducer", -1, 2.1); 2068 2069 return needsQuirk; 2070} 2071 2072- (BOOL)_needsKeyboardEventDisambiguationQuirks 2073{ 2074 static BOOL needsQuirks = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_IE_COMPATIBLE_KEYBOARD_EVENT_DISPATCH) && !applicationIsSafari(); 2075 return needsQuirks; 2076} 2077 2078- (BOOL)_needsFrameLoadDelegateRetainQuirk 2079{ 2080 static BOOL needsQuirk = WKAppVersionCheckLessThan(@"com.equinux.iSale5", -1, 5.6); 2081 return needsQuirk; 2082} 2083 2084static bool needsSelfRetainWhileLoadingQuirk() 2085{ 2086 static bool needsQuirk = applicationIsAperture(); 2087 return needsQuirk; 2088} 2089#endif // !PLATFORM(IOS) 2090 2091- (BOOL)_needsPreHTML5ParserQuirks 2092{ 2093#if !PLATFORM(IOS) 2094 // AOL Instant Messenger and Microsoft My Day contain markup incompatible 2095 // with the new HTML5 parser. If these applications were linked against a 2096 // version of WebKit prior to the introduction of the HTML5 parser, enable 2097 // parser quirks to maintain compatibility. For details, see 2098 // <https://bugs.webkit.org/show_bug.cgi?id=46134> and 2099 // <https://bugs.webkit.org/show_bug.cgi?id=46334>. 2100 static bool isApplicationNeedingParserQuirks = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_HTML5_PARSER) 2101 && (applicationIsAOLInstantMessenger() || applicationIsMicrosoftMyDay()); 2102 2103 // Mail.app must continue to display HTML email that contains quirky markup. 2104 static bool isAppleMail = applicationIsAppleMail(); 2105 2106 return isApplicationNeedingParserQuirks 2107 || isAppleMail 2108#if ENABLE(DASHBOARD_SUPPORT) 2109 // Pre-HTML5 parser quirks are required to remain compatible with many 2110 // Dashboard widgets. See <rdar://problem/8175982>. 2111 || (_private->page && _private->page->settings().usesDashboardBackwardCompatibilityMode()) 2112#endif 2113 || [[self preferences] usePreHTML5ParserQuirks]; 2114#else 2115 static bool isApplicationNeedingParserQuirks = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_HTML5_PARSER) && applicationIsDaijisenDictionary(); 2116 return isApplicationNeedingParserQuirks || [[self preferences] usePreHTML5ParserQuirks]; 2117#endif 2118} 2119 2120- (void)_preferencesChangedNotification:(NSNotification *)notification 2121{ 2122#if PLATFORM(IOS) 2123 // For WebViews that load synchronously, preference changes need to be propagated 2124 // down to WebCore synchronously so that loads in that WebView have the correct 2125 // up-to-date settings. 2126 if (!WebThreadIsLocked()) 2127 WebThreadLock(); 2128 if ([[self mainFrame] _loadsSynchronously]) { 2129#endif 2130 2131 WebPreferences *preferences = (WebPreferences *)[notification object]; 2132 [self _preferencesChanged:preferences]; 2133 2134#if PLATFORM(IOS) 2135 } else { 2136 WebThreadRun(^{ 2137 // It is possible that the prefs object has already changed before the invocation could be called 2138 // on the web thread. This is not possible on TOT which is why they have a simple ASSERT. 2139 WebPreferences *preferences = (WebPreferences *)[notification object]; 2140 if (preferences != [self preferences]) 2141 return; 2142 [self _preferencesChanged:preferences]; 2143 }); 2144 } 2145#endif 2146} 2147 2148- (void)_preferencesChanged:(WebPreferences *)preferences 2149{ 2150 ASSERT(preferences == [self preferences]); 2151 if (!_private->userAgentOverridden) 2152 _private->userAgent = String(); 2153 2154 // Cache this value so we don't have to read NSUserDefaults on each page load 2155 _private->useSiteSpecificSpoofing = [preferences _useSiteSpecificSpoofing]; 2156 2157 // Update corresponding WebCore Settings object. 2158 if (!_private->page) 2159 return; 2160 2161#if PLATFORM(IOS) 2162 // iOS waits to call [WebDatabaseManager sharedWebDatabaseManager] until 2163 // didOneTimeInitialization is true so that we don't initialize databases 2164 // until the first WebView has been created. This is because database 2165 // initialization current requires disk access to populate the origins 2166 // quota map and we want to do this lazily by waiting until WebKit is 2167 // used to display web content in a WebView. The possible cases are: 2168 // - on one time initialize (the first WebView creation) if databases are enabled (default) 2169 // - when databases are dynamically enabled later, and they were disabled at startup (this case) 2170 if (didOneTimeInitialization) { 2171 if ([preferences databasesEnabled]) 2172 [WebDatabaseManager sharedWebDatabaseManager]; 2173 2174 if ([preferences storageTrackerEnabled]) 2175 WebKitInitializeStorageIfNecessary(); 2176 } 2177#endif 2178 2179 Settings& settings = _private->page->settings(); 2180 2181 settings.setCursiveFontFamily([preferences cursiveFontFamily]); 2182 settings.setDefaultFixedFontSize([preferences defaultFixedFontSize]); 2183 settings.setDefaultFontSize([preferences defaultFontSize]); 2184 settings.setDefaultTextEncodingName([preferences defaultTextEncodingName]); 2185 settings.setUsesEncodingDetector([preferences usesEncodingDetector]); 2186 settings.setFantasyFontFamily([preferences fantasyFontFamily]); 2187 settings.setFixedFontFamily([preferences fixedFontFamily]); 2188 settings.setScreenFontSubstitutionEnabled( 2189#if !PLATFORM(IOS) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 2190 [[NSUserDefaults standardUserDefaults] boolForKey:@"NSFontDefaultScreenFontSubstitutionEnabled"] || 2191#endif 2192 [preferences screenFontSubstitutionEnabled] 2193 ); 2194 settings.setForceFTPDirectoryListings([preferences _forceFTPDirectoryListings]); 2195 settings.setFTPDirectoryTemplatePath([preferences _ftpDirectoryTemplatePath]); 2196 settings.setLocalStorageDatabasePath([preferences _localStorageDatabasePath]); 2197 settings.setJavaEnabled([preferences isJavaEnabled]); 2198 settings.setScriptEnabled([preferences isJavaScriptEnabled]); 2199 settings.setWebSecurityEnabled([preferences isWebSecurityEnabled]); 2200 settings.setAllowUniversalAccessFromFileURLs([preferences allowUniversalAccessFromFileURLs]); 2201 settings.setAllowFileAccessFromFileURLs([preferences allowFileAccessFromFileURLs]); 2202 settings.setJavaScriptCanOpenWindowsAutomatically([preferences javaScriptCanOpenWindowsAutomatically]); 2203 settings.setMinimumFontSize([preferences minimumFontSize]); 2204 settings.setMinimumLogicalFontSize([preferences minimumLogicalFontSize]); 2205 settings.setPictographFontFamily([preferences pictographFontFamily]); 2206 settings.setPluginsEnabled([preferences arePlugInsEnabled]); 2207 settings.setLocalStorageEnabled([preferences localStorageEnabled]); 2208 2209 _private->page->enableLegacyPrivateBrowsing([preferences privateBrowsingEnabled]); 2210 settings.setSansSerifFontFamily([preferences sansSerifFontFamily]); 2211 settings.setSerifFontFamily([preferences serifFontFamily]); 2212 settings.setStandardFontFamily([preferences standardFontFamily]); 2213 settings.setLoadsImagesAutomatically([preferences loadsImagesAutomatically]); 2214 settings.setLoadsSiteIconsIgnoringImageLoadingSetting([preferences loadsSiteIconsIgnoringImageLoadingPreference]); 2215#if PLATFORM(IOS) 2216 settings.setShouldPrintBackgrounds(true); 2217#else 2218 settings.setShouldPrintBackgrounds([preferences shouldPrintBackgrounds]); 2219#endif 2220 settings.setShrinksStandaloneImagesToFit([preferences shrinksStandaloneImagesToFit]); 2221 settings.setEditableLinkBehavior(core([preferences editableLinkBehavior])); 2222 settings.setTextDirectionSubmenuInclusionBehavior(core([preferences textDirectionSubmenuInclusionBehavior])); 2223 settings.setDOMPasteAllowed([preferences isDOMPasteAllowed]); 2224 settings.setUsesPageCache([self usesPageCache]); 2225 settings.setPageCacheSupportsPlugins([preferences pageCacheSupportsPlugins]); 2226 settings.setBackForwardCacheExpirationInterval([preferences _backForwardCacheExpirationInterval]); 2227 2228 settings.setDeveloperExtrasEnabled([preferences developerExtrasEnabled]); 2229 settings.setJavaScriptExperimentsEnabled([preferences javaScriptExperimentsEnabled]); 2230 settings.setAuthorAndUserStylesEnabled([preferences authorAndUserStylesEnabled]); 2231 settings.setApplicationChromeMode([preferences applicationChromeModeEnabled]); 2232 2233 settings.setNeedsSiteSpecificQuirks(_private->useSiteSpecificSpoofing); 2234 settings.setWebArchiveDebugModeEnabled([preferences webArchiveDebugModeEnabled]); 2235 settings.setLocalFileContentSniffingEnabled([preferences localFileContentSniffingEnabled]); 2236 settings.setOfflineWebApplicationCacheEnabled([preferences offlineWebApplicationCacheEnabled]); 2237 settings.setJavaScriptCanAccessClipboard([preferences javaScriptCanAccessClipboard]); 2238 settings.setXSSAuditorEnabled([preferences isXSSAuditorEnabled]); 2239 settings.setDNSPrefetchingEnabled([preferences isDNSPrefetchingEnabled]); 2240 2241 // FIXME: Enabling accelerated compositing when WebGL is enabled causes tests to fail on Leopard which expect HW compositing to be disabled. 2242 // Until we fix that, I will comment out the test (CFM) 2243 settings.setAcceleratedCompositingEnabled([preferences acceleratedCompositingEnabled]); 2244 settings.setAcceleratedDrawingEnabled([preferences acceleratedDrawingEnabled]); 2245 settings.setCanvasUsesAcceleratedDrawing([preferences canvasUsesAcceleratedDrawing]); 2246 settings.setShowDebugBorders([preferences showDebugBorders]); 2247 settings.setShowRepaintCounter([preferences showRepaintCounter]); 2248 settings.setWebGLEnabled([preferences webGLEnabled]); 2249 settings.setSubpixelCSSOMElementMetricsEnabled([preferences subpixelCSSOMElementMetricsEnabled]); 2250 2251 settings.setForceSoftwareWebGLRendering([preferences forceSoftwareWebGLRendering]); 2252 settings.setAccelerated2dCanvasEnabled([preferences accelerated2dCanvasEnabled]); 2253 settings.setLoadDeferringEnabled(shouldEnableLoadDeferring()); 2254 settings.setWindowFocusRestricted(shouldRestrictWindowFocus()); 2255 settings.setFrameFlatteningEnabled([preferences isFrameFlatteningEnabled]); 2256 settings.setSpatialNavigationEnabled([preferences isSpatialNavigationEnabled]); 2257 settings.setPaginateDuringLayoutEnabled([preferences paginateDuringLayoutEnabled]); 2258 RuntimeEnabledFeatures::sharedFeatures().setCSSRegionsEnabled([preferences cssRegionsEnabled]); 2259 RuntimeEnabledFeatures::sharedFeatures().setCSSCompositingEnabled([preferences cssCompositingEnabled]); 2260 2261 settings.setAsynchronousSpellCheckingEnabled([preferences asynchronousSpellCheckingEnabled]); 2262 settings.setHyperlinkAuditingEnabled([preferences hyperlinkAuditingEnabled]); 2263 settings.setUsePreHTML5ParserQuirks([self _needsPreHTML5ParserQuirks]); 2264 settings.setInteractiveFormValidationEnabled([self interactiveFormValidationEnabled]); 2265 settings.setValidationMessageTimerMagnification([self validationMessageTimerMagnification]); 2266 2267 settings.setMediaPlaybackRequiresUserGesture([preferences mediaPlaybackRequiresUserGesture]); 2268 settings.setMediaPlaybackAllowsInline([preferences mediaPlaybackAllowsInline]); 2269 settings.setSuppressesIncrementalRendering([preferences suppressesIncrementalRendering]); 2270 settings.setBackspaceKeyNavigationEnabled([preferences backspaceKeyNavigationEnabled]); 2271 settings.setWantsBalancedSetDefersLoadingBehavior([preferences wantsBalancedSetDefersLoadingBehavior]); 2272 settings.setMockScrollbarsEnabled([preferences mockScrollbarsEnabled]); 2273 2274 settings.setShouldRespectImageOrientation([preferences shouldRespectImageOrientation]); 2275 2276 settings.setRequestAnimationFrameEnabled([preferences requestAnimationFrameEnabled]); 2277 settings.setDiagnosticLoggingEnabled([preferences diagnosticLoggingEnabled]); 2278 settings.setLowPowerVideoAudioBufferSizeEnabled([preferences lowPowerVideoAudioBufferSizeEnabled]); 2279 2280 settings.setUseLegacyTextAlignPositionedElementBehavior([preferences useLegacyTextAlignPositionedElementBehavior]); 2281 2282 settings.setShouldConvertPositionStyleOnCopy([preferences shouldConvertPositionStyleOnCopy]); 2283 settings.setEnableInheritURIQueryComponent([preferences isInheritURIQueryComponentEnabled]); 2284 2285 switch ([preferences storageBlockingPolicy]) { 2286 case WebAllowAllStorage: 2287 settings.setStorageBlockingPolicy(SecurityOrigin::AllowAllStorage); 2288 break; 2289 case WebBlockThirdPartyStorage: 2290 settings.setStorageBlockingPolicy(SecurityOrigin::BlockThirdPartyStorage); 2291 break; 2292 case WebBlockAllStorage: 2293 settings.setStorageBlockingPolicy(SecurityOrigin::BlockAllStorage); 2294 break; 2295 } 2296 2297 settings.setPlugInSnapshottingEnabled([preferences plugInSnapshottingEnabled]); 2298 2299 settings.setFixedPositionCreatesStackingContext(true); 2300#if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 10100 2301 settings.setAcceleratedCompositingForFixedPositionEnabled(true); 2302#endif 2303 2304#if PLATFORM(IOS) 2305 settings.setStandalone([preferences _standalone]); 2306 settings.setTelephoneNumberParsingEnabled([preferences _telephoneNumberParsingEnabled]); 2307 settings.setAlwaysUseBaselineOfPrimaryFont([preferences _alwaysUseBaselineOfPrimaryFont]); 2308 settings.setAllowMultiElementImplicitSubmission([preferences _allowMultiElementImplicitFormSubmission]); 2309 settings.setLayoutInterval(std::chrono::milliseconds([preferences _layoutInterval])); 2310 settings.setMaxParseDuration([preferences _maxParseDuration]); 2311 settings.setAlwaysUseAcceleratedOverflowScroll([preferences _alwaysUseAcceleratedOverflowScroll]); 2312 settings.setMediaPlaybackAllowsAirPlay([preferences mediaPlaybackAllowsAirPlay]); 2313 settings.setAudioSessionCategoryOverride([preferences audioSessionCategoryOverride]); 2314 settings.setNetworkDataUsageTrackingEnabled([preferences networkDataUsageTrackingEnabled]); 2315 settings.setNetworkInterfaceName([preferences networkInterfaceName]); 2316 settings.setAVKitEnabled([preferences avKitEnabled]); 2317 settings.setShouldTransformsAffectOverflow(shouldTransformsAffectOverflow()); 2318 settings.setShouldDispatchJavaScriptWindowOnErrorEvents(shouldDispatchJavaScriptWindowOnErrorEvents()); 2319 2320 settings.setPasswordEchoEnabled([preferences _allowPasswordEcho]); 2321 settings.setPasswordEchoDurationInSeconds([preferences _passwordEchoDuration]); 2322 2323 ASSERT_WITH_MESSAGE(settings.pageCacheSupportsPlugins(), "PageCacheSupportsPlugins should be enabled on iOS."); 2324 settings.setDelegatesPageScaling(true); 2325 2326#if ENABLE(IOS_TEXT_AUTOSIZING) 2327 settings.setMinimumZoomFontSize([preferences _minimumZoomFontSize]); 2328#endif 2329#endif // PLATFORM(IOS) 2330 2331#if PLATFORM(MAC) 2332 if ([preferences userStyleSheetEnabled]) { 2333 NSString* location = [[preferences userStyleSheetLocation] _web_originalDataAsString]; 2334 if ([location isEqualToString:@"apple-dashboard://stylesheet"]) 2335 location = @"file:///System/Library/PrivateFrameworks/DashboardClient.framework/Resources/widget.css"; 2336 settings.setUserStyleSheetLocation([NSURL URLWithString:(location ? location : @"")]); 2337 } else 2338 settings.setUserStyleSheetLocation([NSURL URLWithString:@""]); 2339 2340 settings.setNeedsAdobeFrameReloadingQuirk([self _needsAdobeFrameReloadingQuirk]); 2341 settings.setTreatsAnyTextCSSLinkAsStylesheet([self _needsLinkElementTextCSSQuirk]); 2342 settings.setNeedsKeyboardEventDisambiguationQuirks([self _needsKeyboardEventDisambiguationQuirks]); 2343 settings.setEnforceCSSMIMETypeInNoQuirksMode(!WKAppVersionCheckLessThan(@"com.apple.iWeb", -1, 2.1)); 2344 settings.setNeedsIsLoadingInAPISenseQuirk([self _needsIsLoadingInAPISenseQuirk]); 2345 settings.setTextAreasAreResizable([preferences textAreasAreResizable]); 2346 settings.setExperimentalNotificationsEnabled([preferences experimentalNotificationsEnabled]); 2347 settings.setShowsURLsInToolTips([preferences showsURLsInToolTips]); 2348 settings.setShowsToolTipOverTruncatedText([preferences showsToolTipOverTruncatedText]); 2349 settings.setQTKitEnabled([preferences isQTKitEnabled]); 2350 2351 // FIXME: Should we enable this following <rdar://problem/15290404>? 2352 settings.setMultithreadedWebGLEnabled([preferences multithreadedWebGLEnabled]); 2353#endif // PLATFORM(MAC) 2354 2355#if ENABLE(SQL_DATABASE) 2356 DatabaseManager::manager().setIsAvailable([preferences databasesEnabled]); 2357#endif 2358 2359#if ENABLE(MEDIA_SOURCE) 2360 settings.setMediaSourceEnabled([preferences mediaSourceEnabled]); 2361#endif 2362 2363#if ENABLE(SERVICE_CONTROLS) 2364 settings.setImageControlsEnabled([preferences imageControlsEnabled]); 2365#endif 2366 2367#if ENABLE(VIDEO_TRACK) 2368 settings.setShouldDisplaySubtitles([preferences shouldDisplaySubtitles]); 2369 settings.setShouldDisplayCaptions([preferences shouldDisplayCaptions]); 2370 settings.setShouldDisplayTextDescriptions([preferences shouldDisplayTextDescriptions]); 2371#endif 2372 2373#if USE(AVFOUNDATION) 2374 settings.setAVFoundationEnabled([preferences isAVFoundationEnabled]); 2375#endif 2376 2377#if ENABLE(WEB_AUDIO) 2378 settings.setWebAudioEnabled([preferences webAudioEnabled]); 2379#endif 2380 2381#if ENABLE(FULLSCREEN_API) 2382 settings.setFullScreenEnabled([preferences fullScreenEnabled]); 2383#endif 2384 2385#if ENABLE(HIDDEN_PAGE_DOM_TIMER_THROTTLING) 2386 settings.setHiddenPageDOMTimerThrottlingEnabled([preferences hiddenPageDOMTimerThrottlingEnabled]); 2387#endif 2388 2389 settings.setHiddenPageCSSAnimationSuspensionEnabled([preferences hiddenPageCSSAnimationSuspensionEnabled]); 2390 2391#if ENABLE(GAMEPAD) 2392 RuntimeEnabledFeatures::sharedFeatures().setGamepadsEnabled([preferences gamepadsEnabled]); 2393#endif 2394 2395 NSTimeInterval timeout = [preferences incrementalRenderingSuppressionTimeoutInSeconds]; 2396 if (timeout > 0) 2397 settings.setIncrementalRenderingSuppressionTimeoutInSeconds(timeout); 2398 2399 // Application Cache Preferences are stored on the global cache storage manager, not in Settings. 2400 [WebApplicationCache setDefaultOriginQuota:[preferences applicationCacheDefaultOriginQuota]]; 2401 2402 BOOL zoomsTextOnly = [preferences zoomsTextOnly]; 2403 if (_private->zoomsTextOnly != zoomsTextOnly) 2404 [self _setZoomMultiplier:_private->zoomMultiplier isTextOnly:zoomsTextOnly]; 2405 2406#if ENABLE(DISK_IMAGE_CACHE) && PLATFORM(IOS) 2407 DiskImageCache& diskImageCache = WebCore::diskImageCache(); 2408 diskImageCache.setEnabled([preferences diskImageCacheEnabled]); 2409 diskImageCache.setMinimumImageSize([preferences diskImageCacheMinimumImageSize]); 2410 diskImageCache.setMaximumCacheSize([preferences diskImageCacheMaximumCacheSize]); 2411#endif 2412 2413#if PLATFORM(IOS) 2414 [[self window] setTileBordersVisible:[preferences showDebugBorders]]; 2415 [[self window] setTilePaintCountsVisible:[preferences showRepaintCounter]]; 2416 [[self window] setAcceleratedDrawingEnabled:[preferences acceleratedDrawingEnabled]]; 2417 [WAKView _setInterpolationQuality:[preferences _interpolationQuality]]; 2418#endif 2419} 2420 2421static inline IMP getMethod(id o, SEL s) 2422{ 2423 return [o respondsToSelector:s] ? [o methodForSelector:s] : 0; 2424} 2425 2426#if PLATFORM(IOS) 2427- (id)_UIKitDelegateForwarder 2428{ 2429 if (_private->closing) 2430 return nil; 2431 2432 if (!_private->UIKitDelegateForwarder) 2433 _private->UIKitDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->UIKitDelegate defaultTarget:[WebDefaultUIKitDelegate sharedUIKitDelegate]]; 2434 return _private->UIKitDelegateForwarder; 2435} 2436#endif 2437 2438- (void)_cacheResourceLoadDelegateImplementations 2439{ 2440 WebResourceDelegateImplementationCache *cache = &_private->resourceLoadDelegateImplementations; 2441 id delegate = _private->resourceProgressDelegate; 2442 2443 if (!delegate) { 2444 bzero(cache, sizeof(WebResourceDelegateImplementationCache)); 2445 return; 2446 } 2447 2448 cache->didCancelAuthenticationChallengeFunc = getMethod(delegate, @selector(webView:resource:didCancelAuthenticationChallenge:fromDataSource:)); 2449 cache->didFailLoadingWithErrorFromDataSourceFunc = getMethod(delegate, @selector(webView:resource:didFailLoadingWithError:fromDataSource:)); 2450 cache->didFinishLoadingFromDataSourceFunc = getMethod(delegate, @selector(webView:resource:didFinishLoadingFromDataSource:)); 2451 cache->didLoadResourceFromMemoryCacheFunc = getMethod(delegate, @selector(webView:didLoadResourceFromMemoryCache:response:length:fromDataSource:)); 2452 cache->didReceiveAuthenticationChallengeFunc = getMethod(delegate, @selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:)); 2453#if USE(PROTECTION_SPACE_AUTH_CALLBACK) 2454 cache->canAuthenticateAgainstProtectionSpaceFunc = getMethod(delegate, @selector(webView:resource:canAuthenticateAgainstProtectionSpace:forDataSource:)); 2455#endif 2456 2457#if PLATFORM(IOS) 2458 cache->connectionPropertiesFunc = getMethod(delegate, @selector(webView:connectionPropertiesForResource:dataSource:)); 2459 cache->webThreadDidFinishLoadingFromDataSourceFunc = getMethod(delegate, @selector(webThreadWebView:resource:didFinishLoadingFromDataSource:)); 2460 cache->webThreadDidFailLoadingWithErrorFromDataSourceFunc = getMethod(delegate, @selector(webThreadWebView:resource:didFailLoadingWithError:fromDataSource:)); 2461 cache->webThreadIdentifierForRequestFunc = getMethod(delegate, @selector(webThreadWebView:identifierForInitialRequest:fromDataSource:)); 2462 cache->webThreadDidLoadResourceFromMemoryCacheFunc = getMethod(delegate, @selector(webThreadWebView:didLoadResourceFromMemoryCache:response:length:fromDataSource:)); 2463 cache->webThreadWillSendRequestFunc = getMethod(delegate, @selector(webThreadWebView:resource:willSendRequest:redirectResponse:fromDataSource:)); 2464 cache->webThreadDidReceiveResponseFunc = getMethod(delegate, @selector(webThreadWebView:resource:didReceiveResponse:fromDataSource:)); 2465 cache->webThreadDidReceiveContentLengthFunc = getMethod(delegate, @selector(webThreadWebView:resource:didReceiveContentLength:fromDataSource:)); 2466 cache->webThreadWillCacheResponseFunc = getMethod(delegate, @selector(webThreadWebView:resource:willCacheResponse:fromDataSource:)); 2467#endif 2468 2469 cache->didReceiveContentLengthFunc = getMethod(delegate, @selector(webView:resource:didReceiveContentLength:fromDataSource:)); 2470 cache->didReceiveResponseFunc = getMethod(delegate, @selector(webView:resource:didReceiveResponse:fromDataSource:)); 2471 cache->identifierForRequestFunc = getMethod(delegate, @selector(webView:identifierForInitialRequest:fromDataSource:)); 2472 cache->plugInFailedWithErrorFunc = getMethod(delegate, @selector(webView:plugInFailedWithError:dataSource:)); 2473 cache->willCacheResponseFunc = getMethod(delegate, @selector(webView:resource:willCacheResponse:fromDataSource:)); 2474 cache->willSendRequestFunc = getMethod(delegate, @selector(webView:resource:willSendRequest:redirectResponse:fromDataSource:)); 2475 cache->shouldUseCredentialStorageFunc = getMethod(delegate, @selector(webView:resource:shouldUseCredentialStorageForDataSource:)); 2476 cache->shouldPaintBrokenImageForURLFunc = getMethod(delegate, @selector(webView:shouldPaintBrokenImageForURL:)); 2477} 2478 2479- (void)_cacheFrameLoadDelegateImplementations 2480{ 2481 WebFrameLoadDelegateImplementationCache *cache = &_private->frameLoadDelegateImplementations; 2482 id delegate = _private->frameLoadDelegate; 2483 2484 if (!delegate) { 2485 bzero(cache, sizeof(WebFrameLoadDelegateImplementationCache)); 2486 return; 2487 } 2488 2489 cache->didCancelClientRedirectForFrameFunc = getMethod(delegate, @selector(webView:didCancelClientRedirectForFrame:)); 2490 cache->didChangeLocationWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didChangeLocationWithinPageForFrame:)); 2491 cache->didPushStateWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didPushStateWithinPageForFrame:)); 2492 cache->didReplaceStateWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didReplaceStateWithinPageForFrame:)); 2493 cache->didPopStateWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didPopStateWithinPageForFrame:)); 2494#if JSC_OBJC_API_ENABLED 2495 cache->didCreateJavaScriptContextForFrameFunc = getMethod(delegate, @selector(webView:didCreateJavaScriptContext:forFrame:)); 2496#endif 2497 cache->didClearWindowObjectForFrameFunc = getMethod(delegate, @selector(webView:didClearWindowObject:forFrame:)); 2498 cache->didClearWindowObjectForFrameInScriptWorldFunc = getMethod(delegate, @selector(webView:didClearWindowObjectForFrame:inScriptWorld:)); 2499 cache->didClearInspectorWindowObjectForFrameFunc = getMethod(delegate, @selector(webView:didClearInspectorWindowObject:forFrame:)); 2500 cache->didCommitLoadForFrameFunc = getMethod(delegate, @selector(webView:didCommitLoadForFrame:)); 2501 cache->didFailLoadWithErrorForFrameFunc = getMethod(delegate, @selector(webView:didFailLoadWithError:forFrame:)); 2502 cache->didFailProvisionalLoadWithErrorForFrameFunc = getMethod(delegate, @selector(webView:didFailProvisionalLoadWithError:forFrame:)); 2503 cache->didFinishDocumentLoadForFrameFunc = getMethod(delegate, @selector(webView:didFinishDocumentLoadForFrame:)); 2504 cache->didFinishLoadForFrameFunc = getMethod(delegate, @selector(webView:didFinishLoadForFrame:)); 2505 cache->didFirstLayoutInFrameFunc = getMethod(delegate, @selector(webView:didFirstLayoutInFrame:)); 2506 cache->didFirstVisuallyNonEmptyLayoutInFrameFunc = getMethod(delegate, @selector(webView:didFirstVisuallyNonEmptyLayoutInFrame:)); 2507 cache->didLayoutFunc = getMethod(delegate, @selector(webView:didLayout:)); 2508 cache->didHandleOnloadEventsForFrameFunc = getMethod(delegate, @selector(webView:didHandleOnloadEventsForFrame:)); 2509#if ENABLE(ICONDATABASE) 2510 cache->didReceiveIconForFrameFunc = getMethod(delegate, @selector(webView:didReceiveIcon:forFrame:)); 2511#endif 2512 cache->didReceiveServerRedirectForProvisionalLoadForFrameFunc = getMethod(delegate, @selector(webView:didReceiveServerRedirectForProvisionalLoadForFrame:)); 2513 cache->didReceiveTitleForFrameFunc = getMethod(delegate, @selector(webView:didReceiveTitle:forFrame:)); 2514 cache->didStartProvisionalLoadForFrameFunc = getMethod(delegate, @selector(webView:didStartProvisionalLoadForFrame:)); 2515 cache->willCloseFrameFunc = getMethod(delegate, @selector(webView:willCloseFrame:)); 2516 cache->willPerformClientRedirectToURLDelayFireDateForFrameFunc = getMethod(delegate, @selector(webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:)); 2517 cache->windowScriptObjectAvailableFunc = getMethod(delegate, @selector(webView:windowScriptObjectAvailable:)); 2518 cache->didDisplayInsecureContentFunc = getMethod(delegate, @selector(webViewDidDisplayInsecureContent:)); 2519 cache->didRunInsecureContentFunc = getMethod(delegate, @selector(webView:didRunInsecureContent:)); 2520 cache->didDetectXSSFunc = getMethod(delegate, @selector(webView:didDetectXSS:)); 2521 cache->didRemoveFrameFromHierarchyFunc = getMethod(delegate, @selector(webView:didRemoveFrameFromHierarchy:)); 2522#if PLATFORM(IOS) 2523 cache->webThreadDidLayoutFunc = getMethod(delegate, @selector(webThreadWebView:didLayout:)); 2524#endif 2525 2526 // It would be nice to get rid of this code and transition all clients to using didLayout instead of 2527 // didFirstLayoutInFrame and didFirstVisuallyNonEmptyLayoutInFrame. In the meantime, this is required 2528 // for backwards compatibility. 2529 Page* page = core(self); 2530 if (page) { 2531 unsigned milestones = DidFirstLayout; 2532#if PLATFORM(IOS) 2533 milestones |= DidFirstVisuallyNonEmptyLayout; 2534#else 2535 if (cache->didFirstVisuallyNonEmptyLayoutInFrameFunc) 2536 milestones |= DidFirstVisuallyNonEmptyLayout; 2537#endif 2538 page->addLayoutMilestones(static_cast<LayoutMilestones>(milestones)); 2539 } 2540} 2541 2542- (void)_cacheScriptDebugDelegateImplementations 2543{ 2544 WebScriptDebugDelegateImplementationCache *cache = &_private->scriptDebugDelegateImplementations; 2545 id delegate = _private->scriptDebugDelegate; 2546 2547 if (!delegate) { 2548 bzero(cache, sizeof(WebScriptDebugDelegateImplementationCache)); 2549 return; 2550 } 2551 2552 cache->didParseSourceFunc = getMethod(delegate, @selector(webView:didParseSource:baseLineNumber:fromURL:sourceId:forWebFrame:)); 2553 if (cache->didParseSourceFunc) 2554 cache->didParseSourceExpectsBaseLineNumber = YES; 2555 else { 2556 cache->didParseSourceExpectsBaseLineNumber = NO; 2557 cache->didParseSourceFunc = getMethod(delegate, @selector(webView:didParseSource:fromURL:sourceId:forWebFrame:)); 2558 } 2559 2560 cache->failedToParseSourceFunc = getMethod(delegate, @selector(webView:failedToParseSource:baseLineNumber:fromURL:withError:forWebFrame:)); 2561 2562 cache->exceptionWasRaisedFunc = getMethod(delegate, @selector(webView:exceptionWasRaised:hasHandler:sourceId:line:forWebFrame:)); 2563 if (cache->exceptionWasRaisedFunc) 2564 cache->exceptionWasRaisedExpectsHasHandlerFlag = YES; 2565 else { 2566 cache->exceptionWasRaisedExpectsHasHandlerFlag = NO; 2567 cache->exceptionWasRaisedFunc = getMethod(delegate, @selector(webView:exceptionWasRaised:sourceId:line:forWebFrame:)); 2568 } 2569} 2570 2571- (void)_cacheHistoryDelegateImplementations 2572{ 2573 WebHistoryDelegateImplementationCache *cache = &_private->historyDelegateImplementations; 2574 id delegate = _private->historyDelegate; 2575 2576 if (!delegate) { 2577 bzero(cache, sizeof(WebHistoryDelegateImplementationCache)); 2578 return; 2579 } 2580 2581 cache->navigatedFunc = getMethod(delegate, @selector(webView:didNavigateWithNavigationData:inFrame:)); 2582 cache->clientRedirectFunc = getMethod(delegate, @selector(webView:didPerformClientRedirectFromURL:toURL:inFrame:)); 2583 cache->serverRedirectFunc = getMethod(delegate, @selector(webView:didPerformServerRedirectFromURL:toURL:inFrame:)); 2584 cache->deprecatedSetTitleFunc = getMethod(delegate, @selector(webView:updateHistoryTitle:forURL:)); 2585 cache->setTitleFunc = getMethod(delegate, @selector(webView:updateHistoryTitle:forURL:inFrame:)); 2586 cache->populateVisitedLinksFunc = getMethod(delegate, @selector(populateVisitedLinksForWebView:)); 2587} 2588 2589- (id)_policyDelegateForwarder 2590{ 2591#if PLATFORM(IOS) 2592 if (_private->closing) 2593 return nil; 2594#endif 2595 if (!_private->policyDelegateForwarder) 2596 _private->policyDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->policyDelegate defaultTarget:[WebDefaultPolicyDelegate sharedPolicyDelegate]]; 2597 return _private->policyDelegateForwarder; 2598} 2599 2600- (id)_UIDelegateForwarder 2601{ 2602#if PLATFORM(IOS) 2603 if (_private->closing) 2604 return nil; 2605#endif 2606 if (!_private->UIDelegateForwarder) 2607 _private->UIDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->UIDelegate defaultTarget:[WebDefaultUIDelegate sharedUIDelegate]]; 2608 return _private->UIDelegateForwarder; 2609} 2610 2611#if PLATFORM(IOS) 2612- (id)_UIDelegateForSelector:(SEL)selector 2613{ 2614 id delegate = self->_private->UIDelegate; 2615 if ([delegate respondsToSelector:selector]) 2616 return delegate; 2617 2618 delegate = [WebDefaultUIDelegate sharedUIDelegate]; 2619 if ([delegate respondsToSelector:selector]) 2620 return delegate; 2621 2622 return nil; 2623} 2624#endif 2625 2626- (id)_editingDelegateForwarder 2627{ 2628#if PLATFORM(IOS) 2629 if (_private->closing) 2630 return nil; 2631#endif 2632 // This can be called during window deallocation by QTMovieView in the QuickTime Cocoa Plug-in. 2633 // Not sure if that is a bug or not. 2634 if (!_private) 2635 return nil; 2636 2637 if (!_private->editingDelegateForwarder) 2638 _private->editingDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->editingDelegate defaultTarget:[WebDefaultEditingDelegate sharedEditingDelegate]]; 2639 return _private->editingDelegateForwarder; 2640} 2641 2642- (void)_closeWindow 2643{ 2644 [[self _UIDelegateForwarder] webViewClose:self]; 2645} 2646 2647+ (void)_unregisterViewClassAndRepresentationClassForMIMEType:(NSString *)MIMEType 2648{ 2649 [[WebFrameView _viewTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType]; 2650 [[WebDataSource _repTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType]; 2651 2652 // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed) 2653 // in the WebCore MIMEType registry. For now we're doing this in a safe, limited manner 2654 // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness 2655 MIMETypeRegistry::getSupportedNonImageMIMETypes().remove(MIMEType); 2656} 2657 2658+ (void)_registerViewClass:(Class)viewClass representationClass:(Class)representationClass forURLScheme:(NSString *)URLScheme 2659{ 2660 NSString *MIMEType = [self _generatedMIMETypeForURLScheme:URLScheme]; 2661 [self registerViewClass:viewClass representationClass:representationClass forMIMEType:MIMEType]; 2662 2663 // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed) 2664 // in the WebCore MIMEType registry. For now we're doing this in a safe, limited manner 2665 // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness 2666 if ([viewClass class] == [WebHTMLView class]) 2667 MIMETypeRegistry::getSupportedNonImageMIMETypes().add(MIMEType); 2668 2669 // This is used to make _representationExistsForURLScheme faster. 2670 // Without this set, we'd have to create the MIME type each time. 2671 if (schemesWithRepresentationsSet == nil) { 2672 schemesWithRepresentationsSet = [[NSMutableSet alloc] init]; 2673 } 2674 [schemesWithRepresentationsSet addObject:[[[URLScheme lowercaseString] copy] autorelease]]; 2675} 2676 2677+ (NSString *)_generatedMIMETypeForURLScheme:(NSString *)URLScheme 2678{ 2679 return [@"x-apple-web-kit/" stringByAppendingString:[URLScheme lowercaseString]]; 2680} 2681 2682+ (BOOL)_representationExistsForURLScheme:(NSString *)URLScheme 2683{ 2684 return [schemesWithRepresentationsSet containsObject:[URLScheme lowercaseString]]; 2685} 2686 2687+ (BOOL)_canHandleRequest:(NSURLRequest *)request forMainFrame:(BOOL)forMainFrame 2688{ 2689 // FIXME: If <rdar://problem/5217309> gets fixed, this check can be removed. 2690 if (!request) 2691 return NO; 2692 2693 if ([NSURLConnection canHandleRequest:request]) 2694 return YES; 2695 2696 NSString *scheme = [[request URL] scheme]; 2697 2698 // Representations for URL schemes work at the top level. 2699 if (forMainFrame && [self _representationExistsForURLScheme:scheme]) 2700 return YES; 2701 2702 if ([scheme _webkit_isCaseInsensitiveEqualToString:@"applewebdata"]) 2703 return YES; 2704 2705 if ([scheme _webkit_isCaseInsensitiveEqualToString:@"blob"]) 2706 return YES; 2707 2708 return NO; 2709} 2710 2711+ (BOOL)_canHandleRequest:(NSURLRequest *)request 2712{ 2713 return [self _canHandleRequest:request forMainFrame:YES]; 2714} 2715 2716+ (NSString *)_decodeData:(NSData *)data 2717{ 2718 HTMLNames::init(); // this method is used for importing bookmarks at startup, so HTMLNames are likely to be uninitialized yet 2719 return TextResourceDecoder::create("text/html")->decodeAndFlush(static_cast<const char*>([data bytes]), [data length]); // bookmark files are HTML 2720} 2721 2722- (void)_pushPerformingProgrammaticFocus 2723{ 2724 _private->programmaticFocusCount++; 2725} 2726 2727- (void)_popPerformingProgrammaticFocus 2728{ 2729 _private->programmaticFocusCount--; 2730} 2731 2732- (BOOL)_isPerformingProgrammaticFocus 2733{ 2734 return _private->programmaticFocusCount != 0; 2735} 2736 2737#if !PLATFORM(IOS) 2738- (void)_didChangeValueForKey: (NSString *)key 2739{ 2740 LOG (Bindings, "calling didChangeValueForKey: %@", key); 2741 [self didChangeValueForKey: key]; 2742} 2743 2744- (void)_willChangeValueForKey: (NSString *)key 2745{ 2746 LOG (Bindings, "calling willChangeValueForKey: %@", key); 2747 [self willChangeValueForKey: key]; 2748} 2749 2750+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key { 2751 static NSSet *manualNotifyKeys = nil; 2752 if (!manualNotifyKeys) 2753 manualNotifyKeys = [[NSSet alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey, 2754 _WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, _WebMainFrameDocumentKey, 2755 nil]; 2756 if ([manualNotifyKeys containsObject:key]) 2757 return NO; 2758 return YES; 2759} 2760 2761- (NSArray *)_declaredKeys { 2762 static NSArray *declaredKeys = nil; 2763 if (!declaredKeys) 2764 declaredKeys = [[NSArray alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey, 2765 _WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, _WebMainFrameDocumentKey, nil]; 2766 return declaredKeys; 2767} 2768 2769- (void)setObservationInfo:(void *)info 2770{ 2771 _private->observationInfo = info; 2772} 2773 2774- (void *)observationInfo 2775{ 2776 return _private->observationInfo; 2777} 2778 2779- (void)_willChangeBackForwardKeys 2780{ 2781 [self _willChangeValueForKey: _WebCanGoBackKey]; 2782 [self _willChangeValueForKey: _WebCanGoForwardKey]; 2783} 2784 2785- (void)_didChangeBackForwardKeys 2786{ 2787 [self _didChangeValueForKey: _WebCanGoBackKey]; 2788 [self _didChangeValueForKey: _WebCanGoForwardKey]; 2789} 2790 2791- (void)_didStartProvisionalLoadForFrame:(WebFrame *)frame 2792{ 2793 if (needsSelfRetainWhileLoadingQuirk()) 2794 [self retain]; 2795 2796 [self _willChangeBackForwardKeys]; 2797 if (frame == [self mainFrame]){ 2798 // Force an observer update by sending a will/did. 2799 [self _willChangeValueForKey: _WebIsLoadingKey]; 2800 [self _didChangeValueForKey: _WebIsLoadingKey]; 2801 2802 [self _willChangeValueForKey: _WebMainFrameURLKey]; 2803 } 2804 2805 [NSApp setWindowsNeedUpdate:YES]; 2806 2807#if ENABLE(FULLSCREEN_API) 2808 Document* document = core([frame DOMDocument]); 2809 if (Element* element = document ? document->webkitCurrentFullScreenElement() : 0) { 2810 SEL selector = @selector(webView:closeFullScreenWithListener:); 2811 if (_private->UIDelegate && [_private->UIDelegate respondsToSelector:selector]) { 2812 WebKitFullScreenListener *listener = [[WebKitFullScreenListener alloc] initWithElement:element]; 2813 CallUIDelegate(self, selector, listener); 2814 [listener release]; 2815 } else if (_private->newFullscreenController && [_private->newFullscreenController isFullScreen]) { 2816 [_private->newFullscreenController close]; 2817 } 2818 } 2819#endif 2820} 2821 2822- (void)_checkDidPerformFirstNavigation 2823{ 2824 if (_private->_didPerformFirstNavigation) 2825 return; 2826 2827 Page* page = _private->page; 2828 if (!page) 2829 return; 2830 2831 auto& backForwardController = page->backForward(); 2832 2833 if (!backForwardController.backItem()) 2834 return; 2835 2836 _private->_didPerformFirstNavigation = YES; 2837 2838 if (_private->preferences.automaticallyDetectsCacheModel && _private->preferences.cacheModel < WebCacheModelDocumentBrowser) 2839 _private->preferences.cacheModel = WebCacheModelDocumentBrowser; 2840} 2841 2842- (void)_didCommitLoadForFrame:(WebFrame *)frame 2843{ 2844 if (frame == [self mainFrame]) 2845 [self _didChangeValueForKey: _WebMainFrameURLKey]; 2846 2847 [self _checkDidPerformFirstNavigation]; 2848 2849 [NSApp setWindowsNeedUpdate:YES]; 2850} 2851 2852- (void)_didFinishLoadForFrame:(WebFrame *)frame 2853{ 2854 if (needsSelfRetainWhileLoadingQuirk()) 2855 [self performSelector:@selector(release) withObject:nil afterDelay:0]; 2856 2857 [self _didChangeBackForwardKeys]; 2858 if (frame == [self mainFrame]){ 2859 // Force an observer update by sending a will/did. 2860 [self _willChangeValueForKey: _WebIsLoadingKey]; 2861 [self _didChangeValueForKey: _WebIsLoadingKey]; 2862 } 2863 [NSApp setWindowsNeedUpdate:YES]; 2864} 2865 2866- (void)_didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame 2867{ 2868 if (needsSelfRetainWhileLoadingQuirk()) 2869 [self performSelector:@selector(release) withObject:nil afterDelay:0]; 2870 2871 [self _didChangeBackForwardKeys]; 2872 if (frame == [self mainFrame]){ 2873 // Force an observer update by sending a will/did. 2874 [self _willChangeValueForKey: _WebIsLoadingKey]; 2875 [self _didChangeValueForKey: _WebIsLoadingKey]; 2876 } 2877 [NSApp setWindowsNeedUpdate:YES]; 2878} 2879 2880- (void)_didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame 2881{ 2882 if (needsSelfRetainWhileLoadingQuirk()) 2883 [self performSelector:@selector(release) withObject:nil afterDelay:0]; 2884 2885 [self _didChangeBackForwardKeys]; 2886 if (frame == [self mainFrame]){ 2887 // Force an observer update by sending a will/did. 2888 [self _willChangeValueForKey: _WebIsLoadingKey]; 2889 [self _didChangeValueForKey: _WebIsLoadingKey]; 2890 2891 [self _didChangeValueForKey: _WebMainFrameURLKey]; 2892 } 2893 [NSApp setWindowsNeedUpdate:YES]; 2894} 2895 2896- (NSCachedURLResponse *)_cachedResponseForURL:(NSURL *)URL 2897{ 2898 RetainPtr<NSMutableURLRequest *> request = adoptNS([[NSMutableURLRequest alloc] initWithURL:URL]); 2899 [request _web_setHTTPUserAgent:[self userAgentForURL:URL]]; 2900 NSCachedURLResponse *cachedResponse; 2901 2902 if (!_private->page) 2903 return nil; 2904 2905 if (CFURLStorageSessionRef storageSession = _private->page->mainFrame().loader().networkingContext()->storageSession().platformSession()) 2906 cachedResponse = WKCachedResponseForRequest(storageSession, request.get()); 2907 else 2908 cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:request.get()]; 2909 2910 return cachedResponse; 2911} 2912 2913- (void)_writeImageForElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard 2914{ 2915 NSURL *linkURL = [element objectForKey:WebElementLinkURLKey]; 2916 DOMElement *domElement = [element objectForKey:WebElementDOMNodeKey]; 2917 [pasteboard _web_writeImage:(NSImage *)(domElement ? nil : [element objectForKey:WebElementImageKey]) 2918 element:domElement 2919 URL:linkURL ? linkURL : (NSURL *)[element objectForKey:WebElementImageURLKey] 2920 title:[element objectForKey:WebElementImageAltStringKey] 2921 archive:[[element objectForKey:WebElementDOMNodeKey] webArchive] 2922 types:types 2923 source:nil]; 2924} 2925 2926- (void)_writeLinkElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard 2927{ 2928 [pasteboard _web_writeURL:[element objectForKey:WebElementLinkURLKey] 2929 andTitle:[element objectForKey:WebElementLinkLabelKey] 2930 types:types]; 2931} 2932 2933#if ENABLE(DRAG_SUPPORT) 2934- (void)_setInitiatedDrag:(BOOL)initiatedDrag 2935{ 2936 if (!_private->page) 2937 return; 2938 _private->page->dragController().setDidInitiateDrag(initiatedDrag); 2939} 2940#endif 2941 2942#else 2943 2944- (void)_didCommitLoadForFrame:(WebFrame *)frame 2945{ 2946 if (frame == [self mainFrame]) 2947 _private->didDrawTiles = 0; 2948} 2949 2950#endif // PLATFORM(IOS) 2951 2952#if ENABLE(DASHBOARD_SUPPORT) 2953 2954#define DASHBOARD_CONTROL_LABEL @"control" 2955 2956- (void)_addControlRect:(NSRect)bounds clip:(NSRect)clip fromView:(NSView *)view toDashboardRegions:(NSMutableDictionary *)regions 2957{ 2958 NSRect adjustedBounds = bounds; 2959 adjustedBounds.origin = [self convertPoint:bounds.origin fromView:view]; 2960 adjustedBounds.origin.y = [self bounds].size.height - adjustedBounds.origin.y; 2961 adjustedBounds.size = bounds.size; 2962 2963 NSRect adjustedClip; 2964 adjustedClip.origin = [self convertPoint:clip.origin fromView:view]; 2965 adjustedClip.origin.y = [self bounds].size.height - adjustedClip.origin.y; 2966 adjustedClip.size = clip.size; 2967 2968 WebDashboardRegion *region = [[WebDashboardRegion alloc] initWithRect:adjustedBounds 2969 clip:adjustedClip type:WebDashboardRegionTypeScrollerRectangle]; 2970 NSMutableArray *scrollerRegions = [regions objectForKey:DASHBOARD_CONTROL_LABEL]; 2971 if (!scrollerRegions) { 2972 scrollerRegions = [[NSMutableArray alloc] init]; 2973 [regions setObject:scrollerRegions forKey:DASHBOARD_CONTROL_LABEL]; 2974 [scrollerRegions release]; 2975 } 2976 [scrollerRegions addObject:region]; 2977 [region release]; 2978} 2979 2980- (void)_addScrollerDashboardRegionsForFrameView:(FrameView*)frameView dashboardRegions:(NSMutableDictionary *)regions 2981{ 2982 NSView *documentView = [[kit(&frameView->frame()) frameView] documentView]; 2983 2984 for (const auto& widget: frameView->children()) { 2985 if (widget->isFrameView()) { 2986 [self _addScrollerDashboardRegionsForFrameView:toFrameView(widget.get()) dashboardRegions:regions]; 2987 continue; 2988 } 2989 2990 if (!widget->isScrollbar()) 2991 continue; 2992 2993 // FIXME: This should really pass an appropriate clip, but our first try got it wrong, and 2994 // it's not common to need this to be correct in Dashboard widgets. 2995 NSRect bounds = widget->frameRect(); 2996 [self _addControlRect:bounds clip:bounds fromView:documentView toDashboardRegions:regions]; 2997 } 2998} 2999 3000- (void)_addScrollerDashboardRegions:(NSMutableDictionary *)regions from:(NSArray *)views 3001{ 3002 // Add scroller regions for NSScroller and WebCore scrollbars 3003 NSUInteger count = [views count]; 3004 for (NSUInteger i = 0; i < count; i++) { 3005 NSView *view = [views objectAtIndex:i]; 3006 3007 if ([view isKindOfClass:[WebHTMLView class]]) { 3008 if (Frame* coreFrame = core([(WebHTMLView*)view _frame])) { 3009 if (FrameView* coreView = coreFrame->view()) 3010 [self _addScrollerDashboardRegionsForFrameView:coreView dashboardRegions:regions]; 3011 } 3012 } else if ([view isKindOfClass:[NSScroller class]]) { 3013 // AppKit places absent scrollers at -100,-100 3014 if ([view frame].origin.y < 0) 3015 continue; 3016 [self _addControlRect:[view bounds] clip:[view visibleRect] fromView:view toDashboardRegions:regions]; 3017 } 3018 [self _addScrollerDashboardRegions:regions from:[view subviews]]; 3019 } 3020} 3021 3022- (void)_addScrollerDashboardRegions:(NSMutableDictionary *)regions 3023{ 3024 [self _addScrollerDashboardRegions:regions from:[self subviews]]; 3025} 3026 3027- (NSDictionary *)_dashboardRegions 3028{ 3029 // Only return regions from main frame. 3030 Frame* mainFrame = [self _mainCoreFrame]; 3031 if (!mainFrame) 3032 return nil; 3033 3034 const Vector<AnnotatedRegionValue>& regions = mainFrame->document()->annotatedRegions(); 3035 size_t size = regions.size(); 3036 3037 NSMutableDictionary *webRegions = [NSMutableDictionary dictionaryWithCapacity:size]; 3038 for (size_t i = 0; i < size; i++) { 3039 const AnnotatedRegionValue& region = regions[i]; 3040 3041 if (region.type == StyleDashboardRegion::None) 3042 continue; 3043 3044 NSString *label = region.label; 3045 WebDashboardRegionType type = WebDashboardRegionTypeNone; 3046 if (region.type == StyleDashboardRegion::Circle) 3047 type = WebDashboardRegionTypeCircle; 3048 else if (region.type == StyleDashboardRegion::Rectangle) 3049 type = WebDashboardRegionTypeRectangle; 3050 NSMutableArray *regionValues = [webRegions objectForKey:label]; 3051 if (!regionValues) { 3052 regionValues = [[NSMutableArray alloc] initWithCapacity:1]; 3053 [webRegions setObject:regionValues forKey:label]; 3054 [regionValues release]; 3055 } 3056 3057 WebDashboardRegion *webRegion = [[WebDashboardRegion alloc] initWithRect:pixelSnappedIntRect(region.bounds) clip:pixelSnappedIntRect(region.clip) type:type]; 3058 [regionValues addObject:webRegion]; 3059 [webRegion release]; 3060 } 3061 3062 [self _addScrollerDashboardRegions:webRegions]; 3063 3064 return webRegions; 3065} 3066 3067- (void)_setDashboardBehavior:(WebDashboardBehavior)behavior to:(BOOL)flag 3068{ 3069 // FIXME: Remove this blanket assignment once Dashboard and Dashcode implement 3070 // specific support for the backward compatibility mode flag. 3071 if (behavior == WebDashboardBehaviorAllowWheelScrolling && flag == NO && _private->page) 3072 _private->page->settings().setUsesDashboardBackwardCompatibilityMode(true); 3073 3074 switch (behavior) { 3075 case WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows: { 3076 _private->dashboardBehaviorAlwaysSendMouseEventsToAllWindows = flag; 3077 break; 3078 } 3079 case WebDashboardBehaviorAlwaysSendActiveNullEventsToPlugIns: { 3080 _private->dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns = flag; 3081 break; 3082 } 3083 case WebDashboardBehaviorAlwaysAcceptsFirstMouse: { 3084 _private->dashboardBehaviorAlwaysAcceptsFirstMouse = flag; 3085 break; 3086 } 3087 case WebDashboardBehaviorAllowWheelScrolling: { 3088 _private->dashboardBehaviorAllowWheelScrolling = flag; 3089 break; 3090 } 3091 case WebDashboardBehaviorUseBackwardCompatibilityMode: { 3092 if (_private->page) 3093 _private->page->settings().setUsesDashboardBackwardCompatibilityMode(flag); 3094#if ENABLE(LEGACY_CSS_VENDOR_PREFIXES) 3095 RuntimeEnabledFeatures::sharedFeatures().setLegacyCSSVendorPrefixesEnabled(flag); 3096#endif 3097 break; 3098 } 3099 } 3100 3101 // Pre-HTML5 parser quirks should be enabled if Dashboard is in backward 3102 // compatibility mode. See <rdar://problem/8175982>. 3103 if (_private->page) 3104 _private->page->settings().setUsePreHTML5ParserQuirks([self _needsPreHTML5ParserQuirks]); 3105} 3106 3107- (BOOL)_dashboardBehavior:(WebDashboardBehavior)behavior 3108{ 3109 switch (behavior) { 3110 case WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows: { 3111 return _private->dashboardBehaviorAlwaysSendMouseEventsToAllWindows; 3112 } 3113 case WebDashboardBehaviorAlwaysSendActiveNullEventsToPlugIns: { 3114 return _private->dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns; 3115 } 3116 case WebDashboardBehaviorAlwaysAcceptsFirstMouse: { 3117 return _private->dashboardBehaviorAlwaysAcceptsFirstMouse; 3118 } 3119 case WebDashboardBehaviorAllowWheelScrolling: { 3120 return _private->dashboardBehaviorAllowWheelScrolling; 3121 } 3122 case WebDashboardBehaviorUseBackwardCompatibilityMode: { 3123 return _private->page && _private->page->settings().usesDashboardBackwardCompatibilityMode(); 3124 } 3125 } 3126 return NO; 3127} 3128 3129#endif /* ENABLE(DASHBOARD_SUPPORT) */ 3130 3131+ (void)_setShouldUseFontSmoothing:(BOOL)f 3132{ 3133 Font::setShouldUseSmoothing(f); 3134} 3135 3136+ (BOOL)_shouldUseFontSmoothing 3137{ 3138 return Font::shouldUseSmoothing(); 3139} 3140 3141#if !PLATFORM(IOS) 3142+ (void)_setUsesTestModeFocusRingColor:(BOOL)f 3143{ 3144 setUsesTestModeFocusRingColor(f); 3145} 3146 3147+ (BOOL)_usesTestModeFocusRingColor 3148{ 3149 return usesTestModeFocusRingColor(); 3150} 3151#endif 3152 3153#if PLATFORM(IOS) 3154- (void)_setUIKitDelegate:(id)delegate 3155{ 3156 _private->UIKitDelegate = delegate; 3157 [_private->UIKitDelegateForwarder clearTarget]; 3158 [_private->UIKitDelegateForwarder release]; 3159 _private->UIKitDelegateForwarder = nil; 3160} 3161 3162- (id)_UIKitDelegate 3163{ 3164 return _private->UIKitDelegate; 3165} 3166 3167- (void)setWebMailDelegate:(id)delegate 3168{ 3169 _private->WebMailDelegate = delegate; 3170} 3171 3172- (id)_webMailDelegate 3173{ 3174 return _private->WebMailDelegate; 3175} 3176 3177- (id <WebCaretChangeListener>)caretChangeListener 3178{ 3179 return _private->_caretChangeListener; 3180} 3181 3182- (void)setCaretChangeListener:(id <WebCaretChangeListener>)listener 3183{ 3184 _private->_caretChangeListener = listener; 3185} 3186 3187- (NSSet *)caretChangeListeners 3188{ 3189 return _private->_caretChangeListeners; 3190} 3191 3192- (void)addCaretChangeListener:(id <WebCaretChangeListener>)listener 3193{ 3194 if (_private->_caretChangeListeners == nil) { 3195 _private->_caretChangeListeners = [[NSMutableSet alloc] init]; 3196 } 3197 3198 [_private->_caretChangeListeners addObject:listener]; 3199} 3200 3201- (void)removeCaretChangeListener:(id <WebCaretChangeListener>)listener 3202{ 3203 [_private->_caretChangeListeners removeObject:listener]; 3204} 3205 3206- (void)removeAllCaretChangeListeners 3207{ 3208 [_private->_caretChangeListeners removeAllObjects]; 3209} 3210 3211- (void)caretChanged 3212{ 3213 [_private->_caretChangeListener caretChanged]; 3214 NSSet *copy = [_private->_caretChangeListeners copy]; 3215 for (id <WebCaretChangeListener> listener in copy) { 3216 [listener caretChanged]; 3217 } 3218 [copy release]; 3219} 3220 3221- (void)_clearDelegates 3222{ 3223 ASSERT(WebThreadIsLocked() || !WebThreadIsEnabled()); 3224 3225 [self _setFormDelegate:nil]; 3226 [self _setUIKitDelegate:nil]; 3227 [self setCaretChangeListener:nil]; 3228 [self removeAllCaretChangeListeners]; 3229 [self setWebMailDelegate:nil]; 3230 3231 [self setDownloadDelegate:nil]; 3232 [self setEditingDelegate:nil]; 3233 [self setFrameLoadDelegate:nil]; 3234 [self setPolicyDelegate:nil]; 3235 [self setResourceLoadDelegate:nil]; 3236 [self setScriptDebugDelegate:nil]; 3237 [self setUIDelegate:nil]; 3238} 3239 3240- (NSURL *)_displayURL 3241{ 3242 WebThreadLock(); 3243 WebFrame *frame = [self mainFrame]; 3244 // FIXME: <rdar://problem/6362369> We used to get provisionalDataSource here if in provisional state; how do we tell that now? Is this right? 3245 WebDataSource *dataSource = [frame provisionalDataSource]; 3246 if (!dataSource) 3247 dataSource = [frame dataSource]; 3248 NSURL *unreachableURL = [dataSource unreachableURL]; 3249 NSURL *URL = unreachableURL != nil ? unreachableURL : [[dataSource request] URL]; 3250 [[URL retain] autorelease]; 3251 return URL; 3252} 3253#endif // PLATFORM(IOS) 3254 3255#if !PLATFORM(IOS) 3256- (void)setAlwaysShowVerticalScroller:(BOOL)flag 3257{ 3258 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView]; 3259 if (flag) { 3260 [scrollview setVerticalScrollingMode:ScrollbarAlwaysOn andLock:YES]; 3261 } else { 3262 [scrollview setVerticalScrollingModeLocked:NO]; 3263 [scrollview setVerticalScrollingMode:ScrollbarAuto andLock:NO]; 3264 } 3265} 3266 3267- (BOOL)alwaysShowVerticalScroller 3268{ 3269 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView]; 3270 return [scrollview verticalScrollingModeLocked] && [scrollview verticalScrollingMode] == ScrollbarAlwaysOn; 3271} 3272 3273- (void)setAlwaysShowHorizontalScroller:(BOOL)flag 3274{ 3275 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView]; 3276 if (flag) { 3277 [scrollview setHorizontalScrollingMode:ScrollbarAlwaysOn andLock:YES]; 3278 } else { 3279 [scrollview setHorizontalScrollingModeLocked:NO]; 3280 [scrollview setHorizontalScrollingMode:ScrollbarAuto andLock:NO]; 3281 } 3282} 3283 3284- (void)setProhibitsMainFrameScrolling:(BOOL)prohibits 3285{ 3286 if (Frame* mainFrame = [self _mainCoreFrame]) 3287 mainFrame->view()->setProhibitsScrolling(prohibits); 3288} 3289 3290- (BOOL)alwaysShowHorizontalScroller 3291{ 3292 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView]; 3293 return [scrollview horizontalScrollingModeLocked] && [scrollview horizontalScrollingMode] == ScrollbarAlwaysOn; 3294} 3295#endif // !PLATFORM(IOS) 3296 3297- (void)_setUseFastImageScalingMode:(BOOL)flag 3298{ 3299 if (_private->page && _private->page->inLowQualityImageInterpolationMode() != flag) { 3300 _private->page->setInLowQualityImageInterpolationMode(flag); 3301 [self setNeedsDisplay:YES]; 3302 } 3303} 3304 3305- (BOOL)_inFastImageScalingMode 3306{ 3307 if (_private->page) 3308 return _private->page->inLowQualityImageInterpolationMode(); 3309 return NO; 3310} 3311 3312- (BOOL)_cookieEnabled 3313{ 3314 if (_private->page) 3315 return _private->page->settings().cookieEnabled(); 3316 return YES; 3317} 3318 3319- (void)_setCookieEnabled:(BOOL)enable 3320{ 3321 if (_private->page) 3322 _private->page->settings().setCookieEnabled(enable); 3323} 3324 3325#if !PLATFORM(IOS) 3326- (void)_setAdditionalWebPlugInPaths:(NSArray *)newPaths 3327{ 3328 if (!_private->pluginDatabase) 3329 _private->pluginDatabase = [[WebPluginDatabase alloc] init]; 3330 3331 [_private->pluginDatabase setPlugInPaths:newPaths]; 3332 [_private->pluginDatabase refresh]; 3333} 3334#endif 3335 3336#if PLATFORM(IOS) 3337- (BOOL)_locked_plugInsAreRunningInFrame:(WebFrame *)frame 3338{ 3339 // Ask plug-ins in this frame 3340 id <WebDocumentView> documentView = [[frame frameView] documentView]; 3341 if (documentView && [documentView isKindOfClass:[WebHTMLView class]]) { 3342 if ([[(WebHTMLView *)documentView _pluginController] plugInsAreRunning]) 3343 return YES; 3344 } 3345 3346 // Ask plug-ins in child frames 3347 NSArray *childFrames = [frame childFrames]; 3348 unsigned childCount = [childFrames count]; 3349 unsigned childIndex; 3350 for (childIndex = 0; childIndex < childCount; childIndex++) { 3351 if ([self _locked_plugInsAreRunningInFrame:[childFrames objectAtIndex:childIndex]]) 3352 return YES; 3353 } 3354 3355 return NO; 3356} 3357 3358- (BOOL)_pluginsAreRunning 3359{ 3360 WebThreadLock(); 3361 return [self _locked_plugInsAreRunningInFrame:[self mainFrame]]; 3362} 3363 3364- (void)_locked_recursivelyPerformPlugInSelector:(SEL)selector inFrame:(WebFrame *)frame 3365{ 3366 // Send the message to plug-ins in this frame 3367 id <WebDocumentView> documentView = [[frame frameView] documentView]; 3368 if (documentView && [documentView isKindOfClass:[WebHTMLView class]]) 3369 [[(WebHTMLView *)documentView _pluginController] performSelector:selector]; 3370 3371 // Send the message to plug-ins in child frames 3372 NSArray *childFrames = [frame childFrames]; 3373 unsigned childCount = [childFrames count]; 3374 unsigned childIndex; 3375 for (childIndex = 0; childIndex < childCount; childIndex++) { 3376 [self _locked_recursivelyPerformPlugInSelector:selector inFrame:[childFrames objectAtIndex:childIndex]]; 3377 } 3378} 3379 3380- (void)_destroyAllPlugIns 3381{ 3382 WebThreadLock(); 3383 [self _locked_recursivelyPerformPlugInSelector:@selector(destroyAllPlugins) inFrame:[self mainFrame]]; 3384} 3385 3386- (void)_clearBackForwardCache 3387{ 3388 WebThreadRun(^{ 3389 WebKit::MemoryMeasure measurer("[WebView _clearBackForwardCache]"); 3390 BackForwardList* bfList = core([self backForwardList]); 3391 if (!bfList) 3392 return; 3393 3394 BOOL didClearBFCache = bfList->clearAllPageCaches(); 3395 if (WebKit::MemoryMeasure::isLoggingEnabled()) 3396 NSLog(@"[WebView _clearBackForwardCache] %@ empty cache\n", (didClearBFCache ? @"DID" : @"did NOT")); 3397 }); 3398} 3399 3400- (void)_startAllPlugIns 3401{ 3402 WebThreadLock(); 3403 [self _locked_recursivelyPerformPlugInSelector:@selector(startAllPlugins) inFrame:[self mainFrame]]; 3404} 3405 3406- (void)_stopAllPlugIns 3407{ 3408 WebThreadLock(); 3409 [self _locked_recursivelyPerformPlugInSelector:@selector(stopAllPlugins) inFrame:[self mainFrame]]; 3410} 3411 3412- (void)_stopAllPlugInsForPageCache 3413{ 3414 WebThreadLock(); 3415 [self _locked_recursivelyPerformPlugInSelector:@selector(stopPluginsForPageCache) inFrame:[self mainFrame]]; 3416} 3417 3418- (void)_restorePlugInsFromCache 3419{ 3420 WebThreadLock(); 3421 [self _locked_recursivelyPerformPlugInSelector:@selector(restorePluginsFromCache) inFrame:[self mainFrame]]; 3422} 3423 3424- (BOOL)_setMediaLayer:(CALayer*)layer forPluginView:(NSView*)pluginView 3425{ 3426 WebThreadLock(); 3427 3428 Frame* mainCoreFrame = [self _mainCoreFrame]; 3429 for (Frame* frame = mainCoreFrame; frame; frame = frame->tree().traverseNext()) { 3430 FrameView* coreView = frame ? frame->view() : 0; 3431 if (!coreView) 3432 continue; 3433 3434 // Get the GraphicsLayer for this widget. 3435 GraphicsLayer* layerForWidget = coreView->graphicsLayerForPlatformWidget(pluginView); 3436 if (!layerForWidget) 3437 continue; 3438 3439 if (layerForWidget->contentsLayerForMedia() != layer) { 3440 layerForWidget->setContentsToMedia(layer); 3441 // We need to make sure the layer hierachy change is applied immediately. 3442 if (mainCoreFrame->view()) 3443 mainCoreFrame->view()->flushCompositingStateIncludingSubframes(); 3444 return YES; 3445 } 3446 } 3447 3448 return NO; 3449} 3450 3451- (void)_setNeedsUnrestrictedGetMatchedCSSRules:(BOOL)flag 3452{ 3453 if (_private->page) 3454 _private->page->settings().setCrossOriginCheckInGetMatchedCSSRulesDisabled(flag); 3455} 3456#endif // PLATFORM(IOS) 3457 3458- (void)_attachScriptDebuggerToAllFrames 3459{ 3460 for (Frame* frame = [self _mainCoreFrame]; frame; frame = frame->tree().traverseNext()) 3461 [kit(frame) _attachScriptDebugger]; 3462} 3463 3464- (void)_detachScriptDebuggerFromAllFrames 3465{ 3466 for (Frame* frame = [self _mainCoreFrame]; frame; frame = frame->tree().traverseNext()) 3467 [kit(frame) _detachScriptDebugger]; 3468} 3469 3470#if !PLATFORM(IOS) 3471- (void)setBackgroundColor:(NSColor *)backgroundColor 3472{ 3473 if ([_private->backgroundColor isEqual:backgroundColor]) 3474 return; 3475 3476 id old = _private->backgroundColor; 3477 _private->backgroundColor = [backgroundColor retain]; 3478 [old release]; 3479 3480 [[self mainFrame] _updateBackgroundAndUpdatesWhileOffscreen]; 3481} 3482 3483- (NSColor *)backgroundColor 3484{ 3485 return _private->backgroundColor; 3486} 3487#else 3488- (void)setBackgroundColor:(CGColorRef)backgroundColor 3489{ 3490 if (!backgroundColor || CFEqual(_private->backgroundColor, backgroundColor)) 3491 return; 3492 3493 CFTypeRef old = _private->backgroundColor; 3494 CFRetain(backgroundColor); 3495 _private->backgroundColor = backgroundColor; 3496 CFRelease(old); 3497 3498 [[self mainFrame] _updateBackgroundAndUpdatesWhileOffscreen]; 3499} 3500 3501- (CGColorRef)backgroundColor 3502{ 3503 return _private->backgroundColor; 3504} 3505#endif 3506 3507- (BOOL)defersCallbacks 3508{ 3509 if (!_private->page) 3510 return NO; 3511 return _private->page->defersLoading(); 3512} 3513 3514- (void)setDefersCallbacks:(BOOL)defer 3515{ 3516 if (!_private->page) 3517 return; 3518 return _private->page->setDefersLoading(defer); 3519} 3520 3521#if TARGET_OS_IPHONE && USE(QUICK_LOOK) 3522- (NSDictionary *)quickLookContentForURL:(NSURL *)url 3523{ 3524 NSString *uti = qlPreviewConverterUTIForURL(url); 3525 if (!uti) 3526 return nil; 3527 3528 NSString *fileName = qlPreviewConverterFileNameForURL(url); 3529 if (!fileName) 3530 return nil; 3531 3532 return [NSDictionary dictionaryWithObjectsAndKeys: fileName, WebQuickLookFileNameKey, uti, WebQuickLookUTIKey, nil]; 3533} 3534#endif 3535 3536#if PLATFORM(IOS) 3537- (BOOL)_isStopping 3538{ 3539 return _private->isStopping; 3540} 3541 3542- (BOOL)_isClosing 3543{ 3544 return _private->closing; 3545} 3546 3547+ (NSArray *)_productivityDocumentMIMETypes 3548{ 3549#if USE(QUICK_LOOK) 3550 return [QLPreviewGetSupportedMIMETypesSet() allObjects]; 3551#else 3552 return nil; 3553#endif 3554} 3555 3556- (void)_setAllowsMessaging:(BOOL)aFlag 3557{ 3558 _private->allowsMessaging = aFlag; 3559} 3560 3561- (BOOL)_allowsMessaging 3562{ 3563 return _private->allowsMessaging; 3564} 3565 3566- (void)_setFixedLayoutSize:(CGSize)size 3567{ 3568 ASSERT(WebThreadIsLocked()); 3569 _private->fixedLayoutSize = size; 3570 if (Frame* mainFrame = core([self mainFrame])) { 3571 IntSize newSize(size); 3572 mainFrame->view()->setFixedLayoutSize(newSize); 3573 mainFrame->view()->setUseFixedLayout(!newSize.isEmpty()); 3574 [self setNeedsDisplay:YES]; 3575 } 3576} 3577 3578- (CGSize)_fixedLayoutSize 3579{ 3580 return _private->fixedLayoutSize; 3581} 3582 3583- (void)_synchronizeCustomFixedPositionLayoutRect 3584{ 3585 ASSERT(WebThreadIsLocked()); 3586 3587 IntRect newRect; 3588 { 3589 MutexLocker locker(_private->pendingFixedPositionLayoutRectMutex); 3590 if (CGRectIsNull(_private->pendingFixedPositionLayoutRect)) 3591 return; 3592 newRect = enclosingIntRect(_private->pendingFixedPositionLayoutRect); 3593 _private->pendingFixedPositionLayoutRect = CGRectNull; 3594 } 3595 3596 if (Frame* mainFrame = core([self mainFrame])) 3597 mainFrame->view()->setCustomFixedPositionLayoutRect(newRect); 3598} 3599 3600- (void)_setCustomFixedPositionLayoutRectInWebThread:(CGRect)rect synchronize:(BOOL)synchronize 3601{ 3602 { 3603 MutexLocker locker(_private->pendingFixedPositionLayoutRectMutex); 3604 _private->pendingFixedPositionLayoutRect = rect; 3605 } 3606 if (!synchronize) 3607 return; 3608 WebThreadRun(^{ 3609 [self _synchronizeCustomFixedPositionLayoutRect]; 3610 }); 3611} 3612 3613- (void)_setCustomFixedPositionLayoutRect:(CGRect)rect 3614{ 3615 ASSERT(WebThreadIsLocked()); 3616 { 3617 MutexLocker locker(_private->pendingFixedPositionLayoutRectMutex); 3618 _private->pendingFixedPositionLayoutRect = rect; 3619 } 3620 [self _synchronizeCustomFixedPositionLayoutRect]; 3621} 3622 3623- (BOOL)_fetchCustomFixedPositionLayoutRect:(NSRect*)rect 3624{ 3625 MutexLocker locker(_private->pendingFixedPositionLayoutRectMutex); 3626 if (CGRectIsNull(_private->pendingFixedPositionLayoutRect)) 3627 return false; 3628 3629 *rect = _private->pendingFixedPositionLayoutRect; 3630 _private->pendingFixedPositionLayoutRect = CGRectNull; 3631 return true; 3632} 3633 3634- (void)_viewGeometryDidChange 3635{ 3636 ASSERT(WebThreadIsLocked()); 3637 3638 if (Frame* coreFrame = [self _mainCoreFrame]) 3639 coreFrame->viewportOffsetChanged(Frame::IncrementalScrollOffset); 3640} 3641 3642- (void)_overflowScrollPositionChangedTo:(CGPoint)offset forNode:(DOMNode *)domNode isUserScroll:(BOOL)userScroll 3643{ 3644 // Find the frame 3645 Node* node = core(domNode); 3646 Frame* frame = node->document().frame(); 3647 if (!frame) 3648 return; 3649 3650 frame->overflowScrollPositionChangedForNode(roundedIntPoint(offset), node, userScroll); 3651} 3652 3653+ (void)_doNotStartObservingNetworkReachability 3654{ 3655 Settings::setShouldOptOutOfNetworkStateObservation(true); 3656} 3657#endif // PLATFORM(IOS) 3658 3659#if ENABLE(TOUCH_EVENTS) 3660- (NSArray *)_touchEventRegions 3661{ 3662 Frame* frame = [self _mainCoreFrame]; 3663 if (!frame) 3664 return nil; 3665 3666 Document* document = frame->document(); 3667 if (!document) 3668 return nil; 3669 3670 Vector<IntRect> rects; 3671 document->getTouchRects(rects); 3672 3673 if (rects.size() == 0) 3674 return nil; 3675 3676 NSMutableArray *eventRegionArray = [[[NSMutableArray alloc] initWithCapacity:rects.size()] autorelease]; 3677 3678 Vector<IntRect>::const_iterator end = rects.end(); 3679 for (Vector<IntRect>::const_iterator it = rects.begin(); it != end; ++it) { 3680 const IntRect& rect = *it; 3681 if (rect.isEmpty()) 3682 continue; 3683 3684 // The event region wants this points in this order: 3685 // p2------p3 3686 // | | 3687 // p1------p4 3688 // 3689 WebEventRegion *eventRegion = [[WebEventRegion alloc] initWithPoints:FloatPoint(rect.x(), rect.maxY()) 3690 :FloatPoint(rect.x(), rect.y()) 3691 :FloatPoint(rect.maxX(), rect.y()) 3692 :FloatPoint(rect.maxX(), rect.maxY())]; 3693 if (eventRegion) { 3694 [eventRegionArray addObject:eventRegion]; 3695 [eventRegion release]; 3696 } 3697 } 3698 3699 return eventRegionArray; 3700} 3701#endif // ENABLE(TOUCH_EVENTS) 3702 3703// For backwards compatibility with the WebBackForwardList API, we honor both 3704// a per-WebView and a per-preferences setting for whether to use the page cache. 3705 3706- (BOOL)usesPageCache 3707{ 3708 return _private->usesPageCache && [[self preferences] usesPageCache]; 3709} 3710 3711- (void)setUsesPageCache:(BOOL)usesPageCache 3712{ 3713 _private->usesPageCache = usesPageCache; 3714 3715 // Update our own settings and post the public notification only 3716 [self _preferencesChanged:[self preferences]]; 3717 [[self preferences] _postPreferencesChangedAPINotification]; 3718} 3719 3720- (WebHistoryItem *)_globalHistoryItem 3721{ 3722 if (!_private) 3723 return nil; 3724 3725 return kit(_private->_globalHistoryItem.get()); 3726} 3727 3728- (void)_setGlobalHistoryItem:(HistoryItem*)historyItem 3729{ 3730 _private->_globalHistoryItem = historyItem; 3731} 3732 3733- (WebTextIterator *)textIteratorForRect:(NSRect)rect 3734{ 3735 IntPoint rectStart(rect.origin.x, rect.origin.y); 3736 IntPoint rectEnd(rect.origin.x + rect.size.width, rect.origin.y + rect.size.height); 3737 3738 Frame* coreFrame = [self _mainCoreFrame]; 3739 if (!coreFrame) 3740 return nil; 3741 3742 VisibleSelection selectionInsideRect(coreFrame->visiblePositionForPoint(rectStart), coreFrame->visiblePositionForPoint(rectEnd)); 3743 3744 return [[[WebTextIterator alloc] initWithRange:kit(selectionInsideRect.toNormalizedRange().get())] autorelease]; 3745} 3746 3747#if ENABLE(DASHBOARD_SUPPORT) 3748- (void)handleAuthenticationForResource:(id)identifier challenge:(NSURLAuthenticationChallenge *)challenge fromDataSource:(WebDataSource *)dataSource 3749{ 3750 NSWindow *window = [self hostWindow] ? [self hostWindow] : [self window]; 3751 [[WebPanelAuthenticationHandler sharedHandler] startAuthentication:challenge window:window]; 3752} 3753#endif 3754 3755#if !PLATFORM(IOS) 3756- (void)_clearUndoRedoOperations 3757{ 3758 if (!_private->page) 3759 return; 3760 _private->page->clearUndoRedoOperations(); 3761} 3762#endif 3763 3764- (void)_executeCoreCommandByName:(NSString *)name value:(NSString *)value 3765{ 3766 Frame* coreFrame = [self _mainCoreFrame]; 3767 if (!coreFrame) 3768 return; 3769 coreFrame->editor().command(name).execute(value); 3770} 3771 3772- (void)_clearMainFrameName 3773{ 3774 _private->page->mainFrame().tree().clearName(); 3775} 3776 3777- (void)setSelectTrailingWhitespaceEnabled:(BOOL)flag 3778{ 3779 if (_private->page->settings().selectTrailingWhitespaceEnabled() != flag) { 3780 _private->page->settings().setSelectTrailingWhitespaceEnabled(flag); 3781 [self setSmartInsertDeleteEnabled:!flag]; 3782 } 3783} 3784 3785- (BOOL)isSelectTrailingWhitespaceEnabled 3786{ 3787 return _private->page->settings().selectTrailingWhitespaceEnabled(); 3788} 3789 3790- (void)setMemoryCacheDelegateCallsEnabled:(BOOL)enabled 3791{ 3792 _private->page->setMemoryCacheClientCallsEnabled(enabled); 3793} 3794 3795- (BOOL)areMemoryCacheDelegateCallsEnabled 3796{ 3797 return _private->page->areMemoryCacheClientCallsEnabled(); 3798} 3799 3800#if !PLATFORM(IOS) 3801+ (NSCursor *)_pointingHandCursor 3802{ 3803 return handCursor().platformCursor(); 3804} 3805#endif 3806 3807- (BOOL)_postsAcceleratedCompositingNotifications 3808{ 3809 return _private->postsAcceleratedCompositingNotifications; 3810} 3811- (void)_setPostsAcceleratedCompositingNotifications:(BOOL)flag 3812{ 3813 _private->postsAcceleratedCompositingNotifications = flag; 3814} 3815 3816- (BOOL)_isUsingAcceleratedCompositing 3817{ 3818 Frame* coreFrame = [self _mainCoreFrame]; 3819 for (Frame* frame = coreFrame; frame; frame = frame->tree().traverseNext(coreFrame)) { 3820 NSView *documentView = [[kit(frame) frameView] documentView]; 3821 if ([documentView isKindOfClass:[WebHTMLView class]] && [(WebHTMLView *)documentView _isUsingAcceleratedCompositing]) 3822 return YES; 3823 } 3824 3825 return NO; 3826} 3827 3828- (void)_setBaseCTM:(CGAffineTransform)transform forContext:(CGContextRef)context 3829{ 3830 WKSetBaseCTM(context, transform); 3831} 3832 3833- (BOOL)interactiveFormValidationEnabled 3834{ 3835 return _private->interactiveFormValidationEnabled; 3836} 3837 3838- (void)setInteractiveFormValidationEnabled:(BOOL)enabled 3839{ 3840 _private->interactiveFormValidationEnabled = enabled; 3841} 3842 3843- (int)validationMessageTimerMagnification 3844{ 3845 return _private->validationMessageTimerMagnification; 3846} 3847 3848- (void)setValidationMessageTimerMagnification:(int)newValue 3849{ 3850 _private->validationMessageTimerMagnification = newValue; 3851} 3852 3853- (BOOL)_isSoftwareRenderable 3854{ 3855 Frame* coreFrame = [self _mainCoreFrame]; 3856 for (Frame* frame = coreFrame; frame; frame = frame->tree().traverseNext(coreFrame)) { 3857 if (FrameView* view = frame->view()) { 3858 if (!view->isSoftwareRenderable()) 3859 return NO; 3860 } 3861 } 3862 3863 return YES; 3864} 3865 3866- (void)_setIncludesFlattenedCompositingLayersWhenDrawingToBitmap:(BOOL)flag 3867{ 3868 _private->includesFlattenedCompositingLayersWhenDrawingToBitmap = flag; 3869} 3870 3871- (BOOL)_includesFlattenedCompositingLayersWhenDrawingToBitmap 3872{ 3873 return _private->includesFlattenedCompositingLayersWhenDrawingToBitmap; 3874} 3875 3876- (void)setTracksRepaints:(BOOL)flag 3877{ 3878 Frame* coreFrame = [self _mainCoreFrame]; 3879 if (FrameView* view = coreFrame->view()) 3880 view->setTracksRepaints(flag); 3881} 3882 3883- (BOOL)isTrackingRepaints 3884{ 3885 Frame* coreFrame = [self _mainCoreFrame]; 3886 if (FrameView* view = coreFrame->view()) 3887 return view->isTrackingRepaints(); 3888 3889 return NO; 3890} 3891 3892- (void)resetTrackedRepaints 3893{ 3894 Frame* coreFrame = [self _mainCoreFrame]; 3895 if (FrameView* view = coreFrame->view()) 3896 view->resetTrackedRepaints(); 3897} 3898 3899- (NSArray*)trackedRepaintRects 3900{ 3901 Frame* coreFrame = [self _mainCoreFrame]; 3902 FrameView* view = coreFrame->view(); 3903 if (!view || !view->isTrackingRepaints()) 3904 return nil; 3905 3906 const Vector<FloatRect>& repaintRects = view->trackedRepaintRects(); 3907 NSMutableArray* rectsArray = [[NSMutableArray alloc] initWithCapacity:repaintRects.size()]; 3908 3909 for (unsigned i = 0; i < repaintRects.size(); ++i) 3910 [rectsArray addObject:[NSValue valueWithRect:pixelSnappedIntRect(LayoutRect(repaintRects[i]))]]; 3911 3912 return [rectsArray autorelease]; 3913} 3914 3915#if !PLATFORM(IOS) 3916- (NSPasteboard *)_insertionPasteboard 3917{ 3918 return _private ? _private->insertionPasteboard : nil; 3919} 3920#endif 3921 3922+ (void)_addOriginAccessWhitelistEntryWithSourceOrigin:(NSString *)sourceOrigin destinationProtocol:(NSString *)destinationProtocol destinationHost:(NSString *)destinationHost allowDestinationSubdomains:(BOOL)allowDestinationSubdomains 3923{ 3924 SecurityPolicy::addOriginAccessWhitelistEntry(*SecurityOrigin::createFromString(sourceOrigin), destinationProtocol, destinationHost, allowDestinationSubdomains); 3925} 3926 3927+ (void)_removeOriginAccessWhitelistEntryWithSourceOrigin:(NSString *)sourceOrigin destinationProtocol:(NSString *)destinationProtocol destinationHost:(NSString *)destinationHost allowDestinationSubdomains:(BOOL)allowDestinationSubdomains 3928{ 3929 SecurityPolicy::removeOriginAccessWhitelistEntry(*SecurityOrigin::createFromString(sourceOrigin), destinationProtocol, destinationHost, allowDestinationSubdomains); 3930} 3931 3932+ (void)_resetOriginAccessWhitelists 3933{ 3934 SecurityPolicy::resetOriginAccessWhitelists(); 3935} 3936 3937- (BOOL)_isViewVisible 3938{ 3939 if (![self window]) 3940 return false; 3941 3942 if (![[self window] isVisible]) 3943 return false; 3944 3945 if ([self isHiddenOrHasHiddenAncestor]) 3946 return false; 3947 3948 return true; 3949} 3950 3951- (void)_updateVisibilityState 3952{ 3953 if (_private && _private->page) 3954 [self _setIsVisible:[self _isViewVisible]]; 3955} 3956 3957- (void)_updateActiveState 3958{ 3959 if (_private && _private->page) 3960#if PLATFORM(IOS) 3961 _private->page->focusController().setActive([[self window] isKeyWindow]); 3962#else 3963 _private->page->focusController().setActive([[self window] _hasKeyAppearance]); 3964#endif 3965} 3966 3967static Vector<String> toStringVector(NSArray* patterns) 3968{ 3969 Vector<String> patternsVector; 3970 3971 NSUInteger count = [patterns count]; 3972 if (!count) 3973 return patternsVector; 3974 3975 for (NSUInteger i = 0; i < count; ++i) { 3976 id entry = [patterns objectAtIndex:i]; 3977 if ([entry isKindOfClass:[NSString class]]) 3978 patternsVector.append(String((NSString *)entry)); 3979 } 3980 return patternsVector; 3981} 3982 3983+ (void)_addUserScriptToGroup:(NSString *)groupName world:(WebScriptWorld *)world source:(NSString *)source url:(NSURL *)url 3984 whitelist:(NSArray *)whitelist blacklist:(NSArray *)blacklist 3985 injectionTime:(WebUserScriptInjectionTime)injectionTime 3986{ 3987 [WebView _addUserScriptToGroup:groupName world:world source:source url:url whitelist:whitelist blacklist:blacklist injectionTime:injectionTime injectedFrames:WebInjectInAllFrames]; 3988} 3989 3990+ (void)_addUserScriptToGroup:(NSString *)groupName world:(WebScriptWorld *)world source:(NSString *)source url:(NSURL *)url 3991 whitelist:(NSArray *)whitelist blacklist:(NSArray *)blacklist 3992 injectionTime:(WebUserScriptInjectionTime)injectionTime 3993 injectedFrames:(WebUserContentInjectedFrames)injectedFrames 3994{ 3995 String group(groupName); 3996 if (group.isEmpty()) 3997 return; 3998 3999 PageGroup* pageGroup = PageGroup::pageGroup(group); 4000 if (!pageGroup) 4001 return; 4002 4003 if (!world) 4004 return; 4005 4006 pageGroup->addUserScriptToWorld(*core(world), source, url, toStringVector(whitelist), toStringVector(blacklist), 4007 injectionTime == WebInjectAtDocumentStart ? InjectAtDocumentStart : InjectAtDocumentEnd, 4008 injectedFrames == WebInjectInAllFrames ? InjectInAllFrames : InjectInTopFrameOnly); 4009} 4010 4011+ (void)_addUserStyleSheetToGroup:(NSString *)groupName world:(WebScriptWorld *)world source:(NSString *)source url:(NSURL *)url 4012 whitelist:(NSArray *)whitelist blacklist:(NSArray *)blacklist 4013{ 4014 [WebView _addUserStyleSheetToGroup:groupName world:world source:source url:url whitelist:whitelist blacklist:blacklist injectedFrames:WebInjectInAllFrames]; 4015} 4016 4017+ (void)_addUserStyleSheetToGroup:(NSString *)groupName world:(WebScriptWorld *)world source:(NSString *)source url:(NSURL *)url 4018 whitelist:(NSArray *)whitelist blacklist:(NSArray *)blacklist 4019 injectedFrames:(WebUserContentInjectedFrames)injectedFrames 4020{ 4021 String group(groupName); 4022 if (group.isEmpty()) 4023 return; 4024 4025 PageGroup* pageGroup = PageGroup::pageGroup(group); 4026 if (!pageGroup) 4027 return; 4028 4029 if (!world) 4030 return; 4031 4032 pageGroup->addUserStyleSheetToWorld(*core(world), source, url, toStringVector(whitelist), toStringVector(blacklist), injectedFrames == WebInjectInAllFrames ? InjectInAllFrames : InjectInTopFrameOnly); 4033} 4034 4035+ (void)_removeUserScriptFromGroup:(NSString *)groupName world:(WebScriptWorld *)world url:(NSURL *)url 4036{ 4037 String group(groupName); 4038 if (group.isEmpty()) 4039 return; 4040 4041 PageGroup* pageGroup = PageGroup::pageGroup(group); 4042 if (!pageGroup) 4043 return; 4044 4045 if (!world) 4046 return; 4047 4048 pageGroup->removeUserScriptFromWorld(*core(world), url); 4049} 4050 4051+ (void)_removeUserStyleSheetFromGroup:(NSString *)groupName world:(WebScriptWorld *)world url:(NSURL *)url 4052{ 4053 String group(groupName); 4054 if (group.isEmpty()) 4055 return; 4056 4057 PageGroup* pageGroup = PageGroup::pageGroup(group); 4058 if (!pageGroup) 4059 return; 4060 4061 if (!world) 4062 return; 4063 4064 pageGroup->removeUserStyleSheetFromWorld(*core(world), url); 4065} 4066 4067+ (void)_removeUserScriptsFromGroup:(NSString *)groupName world:(WebScriptWorld *)world 4068{ 4069 String group(groupName); 4070 if (group.isEmpty()) 4071 return; 4072 4073 PageGroup* pageGroup = PageGroup::pageGroup(group); 4074 if (!pageGroup) 4075 return; 4076 4077 if (!world) 4078 return; 4079 4080 pageGroup->removeUserScriptsFromWorld(*core(world)); 4081} 4082 4083+ (void)_removeUserStyleSheetsFromGroup:(NSString *)groupName world:(WebScriptWorld *)world 4084{ 4085 String group(groupName); 4086 if (group.isEmpty()) 4087 return; 4088 4089 PageGroup* pageGroup = PageGroup::pageGroup(group); 4090 if (!pageGroup) 4091 return; 4092 4093 if (!world) 4094 return; 4095 4096 pageGroup->removeUserStyleSheetsFromWorld(*core(world)); 4097} 4098 4099+ (void)_removeAllUserContentFromGroup:(NSString *)groupName 4100{ 4101 String group(groupName); 4102 if (group.isEmpty()) 4103 return; 4104 4105 PageGroup* pageGroup = PageGroup::pageGroup(group); 4106 if (!pageGroup) 4107 return; 4108 4109 pageGroup->removeAllUserContent(); 4110} 4111 4112- (BOOL)allowsNewCSSAnimationsWhileSuspended 4113{ 4114 Frame* frame = core([self mainFrame]); 4115 if (frame) 4116 return frame->animation().allowsNewAnimationsWhileSuspended(); 4117 4118 return false; 4119} 4120 4121- (void)setAllowsNewCSSAnimationsWhileSuspended:(BOOL)allowed 4122{ 4123 Frame* frame = core([self mainFrame]); 4124 if (frame) 4125 frame->animation().setAllowsNewAnimationsWhileSuspended(allowed); 4126} 4127 4128- (BOOL)cssAnimationsSuspended 4129{ 4130 // should ask the page! 4131 Frame* frame = core([self mainFrame]); 4132 if (frame) 4133 return frame->animation().isSuspended(); 4134 4135 return false; 4136} 4137 4138- (void)setCSSAnimationsSuspended:(BOOL)suspended 4139{ 4140 Frame* frame = core([self mainFrame]); 4141 if (suspended == frame->animation().isSuspended()) 4142 return; 4143 4144 if (suspended) 4145 frame->animation().suspendAnimations(); 4146 else 4147 frame->animation().resumeAnimations(); 4148} 4149 4150+ (void)_setDomainRelaxationForbidden:(BOOL)forbidden forURLScheme:(NSString *)scheme 4151{ 4152 SchemeRegistry::setDomainRelaxationForbiddenForURLScheme(forbidden, scheme); 4153} 4154 4155+ (void)_registerURLSchemeAsSecure:(NSString *)scheme 4156{ 4157 SchemeRegistry::registerURLSchemeAsSecure(scheme); 4158} 4159 4160+ (void)_registerURLSchemeAsAllowingLocalStorageAccessInPrivateBrowsing:(NSString *)scheme 4161{ 4162 SchemeRegistry::registerURLSchemeAsAllowingLocalStorageAccessInPrivateBrowsing(scheme); 4163} 4164 4165+ (void)_registerURLSchemeAsAllowingDatabaseAccessInPrivateBrowsing:(NSString *)scheme 4166{ 4167 SchemeRegistry::registerURLSchemeAsAllowingDatabaseAccessInPrivateBrowsing(scheme); 4168} 4169 4170- (void)_scaleWebView:(float)scale atOrigin:(NSPoint)origin 4171{ 4172 _private->page->setPageScaleFactor(scale, IntPoint(origin)); 4173} 4174 4175- (float)_viewScaleFactor 4176{ 4177 return _private->page->pageScaleFactor(); 4178} 4179 4180- (void)_setUseFixedLayout:(BOOL)fixed 4181{ 4182 Frame* coreFrame = [self _mainCoreFrame]; 4183 if (!coreFrame) 4184 return; 4185 4186 FrameView* view = coreFrame->view(); 4187 if (!view) 4188 return; 4189 4190 view->setUseFixedLayout(fixed); 4191 if (!fixed) 4192 view->setFixedLayoutSize(IntSize()); 4193} 4194 4195#if !PLATFORM(IOS) 4196- (void)_setFixedLayoutSize:(NSSize)size 4197{ 4198 Frame* coreFrame = [self _mainCoreFrame]; 4199 if (!coreFrame) 4200 return; 4201 4202 FrameView* view = coreFrame->view(); 4203 if (!view) 4204 return; 4205 4206 view->setFixedLayoutSize(IntSize(size)); 4207 view->forceLayout(); 4208} 4209#endif 4210 4211- (BOOL)_useFixedLayout 4212{ 4213 Frame* coreFrame = [self _mainCoreFrame]; 4214 if (!coreFrame) 4215 return NO; 4216 4217 FrameView* view = coreFrame->view(); 4218 if (!view) 4219 return NO; 4220 4221 return view->useFixedLayout(); 4222} 4223 4224#if !PLATFORM(IOS) 4225- (NSSize)_fixedLayoutSize 4226{ 4227 Frame* coreFrame = [self _mainCoreFrame]; 4228 if (!coreFrame) 4229 return IntSize(); 4230 4231 FrameView* view = coreFrame->view(); 4232 if (!view) 4233 return IntSize(); 4234 4235 return view->fixedLayoutSize(); 4236} 4237#endif 4238 4239- (void)_setPaginationMode:(WebPaginationMode)paginationMode 4240{ 4241 Page* page = core(self); 4242 if (!page) 4243 return; 4244 4245 Pagination pagination = page->pagination(); 4246 switch (paginationMode) { 4247 case WebPaginationModeUnpaginated: 4248 pagination.mode = Pagination::Unpaginated; 4249 break; 4250 case WebPaginationModeLeftToRight: 4251 pagination.mode = Pagination::LeftToRightPaginated; 4252 break; 4253 case WebPaginationModeRightToLeft: 4254 pagination.mode = Pagination::RightToLeftPaginated; 4255 break; 4256 case WebPaginationModeTopToBottom: 4257 pagination.mode = Pagination::TopToBottomPaginated; 4258 break; 4259 case WebPaginationModeBottomToTop: 4260 pagination.mode = Pagination::BottomToTopPaginated; 4261 break; 4262 default: 4263 return; 4264 } 4265 4266 page->setPagination(pagination); 4267} 4268 4269- (WebPaginationMode)_paginationMode 4270{ 4271 Page* page = core(self); 4272 if (!page) 4273 return WebPaginationModeUnpaginated; 4274 4275 switch (page->pagination().mode) { 4276 case Pagination::Unpaginated: 4277 return WebPaginationModeUnpaginated; 4278 case Pagination::LeftToRightPaginated: 4279 return WebPaginationModeLeftToRight; 4280 case Pagination::RightToLeftPaginated: 4281 return WebPaginationModeRightToLeft; 4282 case Pagination::TopToBottomPaginated: 4283 return WebPaginationModeTopToBottom; 4284 case Pagination::BottomToTopPaginated: 4285 return WebPaginationModeBottomToTop; 4286 } 4287 4288 ASSERT_NOT_REACHED(); 4289 return WebPaginationModeUnpaginated; 4290} 4291 4292- (void)_listenForLayoutMilestones:(WebLayoutMilestones)layoutMilestones 4293{ 4294 Page* page = core(self); 4295 if (!page) 4296 return; 4297 4298 page->addLayoutMilestones(coreLayoutMilestones(layoutMilestones)); 4299} 4300 4301- (WebLayoutMilestones)_layoutMilestones 4302{ 4303 Page* page = core(self); 4304 if (!page) 4305 return 0; 4306 4307 return kitLayoutMilestones(page->requestedLayoutMilestones()); 4308} 4309 4310- (WebPageVisibilityState)_visibilityState 4311{ 4312 if (_private->page) 4313 return kit(_private->page->visibilityState()); 4314 return WebPageVisibilityStateVisible; 4315} 4316 4317- (void)_setIsVisible:(BOOL)isVisible 4318{ 4319 if (_private->page) 4320 _private->page->setIsVisible(isVisible); 4321} 4322 4323- (void)_setVisibilityState:(WebPageVisibilityState)visibilityState isInitialState:(BOOL)isInitialState 4324{ 4325 UNUSED_PARAM(isInitialState); 4326 4327 if (_private->page) { 4328 _private->page->setIsVisible(visibilityState == WebPageVisibilityStateVisible); 4329 if (visibilityState == WebPageVisibilityStatePrerender) 4330 _private->page->setIsPrerender(); 4331 } 4332} 4333 4334- (void)_setPaginationBehavesLikeColumns:(BOOL)behavesLikeColumns 4335{ 4336 Page* page = core(self); 4337 if (!page) 4338 return; 4339 4340 Pagination pagination = page->pagination(); 4341 pagination.behavesLikeColumns = behavesLikeColumns; 4342 4343 page->setPagination(pagination); 4344} 4345 4346- (BOOL)_paginationBehavesLikeColumns 4347{ 4348 Page* page = core(self); 4349 if (!page) 4350 return NO; 4351 4352 return page->pagination().behavesLikeColumns; 4353} 4354 4355- (void)_setPageLength:(CGFloat)pageLength 4356{ 4357 Page* page = core(self); 4358 if (!page) 4359 return; 4360 4361 Pagination pagination = page->pagination(); 4362 pagination.pageLength = pageLength; 4363 4364 page->setPagination(pagination); 4365} 4366 4367- (CGFloat)_pageLength 4368{ 4369 Page* page = core(self); 4370 if (!page) 4371 return 1; 4372 4373 return page->pagination().pageLength; 4374} 4375 4376- (void)_setGapBetweenPages:(CGFloat)pageGap 4377{ 4378 Page* page = core(self); 4379 if (!page) 4380 return; 4381 4382 Pagination pagination = page->pagination(); 4383 pagination.gap = pageGap; 4384 page->setPagination(pagination); 4385} 4386 4387- (CGFloat)_gapBetweenPages 4388{ 4389 Page* page = core(self); 4390 if (!page) 4391 return 0; 4392 4393 return page->pagination().gap; 4394} 4395 4396- (NSUInteger)_pageCount 4397{ 4398 Page* page = core(self); 4399 if (!page) 4400 return 0; 4401 4402 return page->pageCount(); 4403} 4404 4405#if !PLATFORM(IOS) 4406- (CGFloat)_backingScaleFactor 4407{ 4408 return [self _deviceScaleFactor]; 4409} 4410 4411- (void)_setCustomBackingScaleFactor:(CGFloat)customScaleFactor 4412{ 4413 float oldScaleFactor = [self _deviceScaleFactor]; 4414 4415 _private->customDeviceScaleFactor = customScaleFactor; 4416 4417 if (oldScaleFactor != [self _deviceScaleFactor]) 4418 _private->page->setDeviceScaleFactor([self _deviceScaleFactor]); 4419} 4420#endif 4421 4422- (NSUInteger)markAllMatchesForText:(NSString *)string caseSensitive:(BOOL)caseFlag highlight:(BOOL)highlight limit:(NSUInteger)limit 4423{ 4424 return [self countMatchesForText:string options:(caseFlag ? 0 : WebFindOptionsCaseInsensitive) highlight:highlight limit:limit markMatches:YES]; 4425} 4426 4427- (NSUInteger)countMatchesForText:(NSString *)string caseSensitive:(BOOL)caseFlag highlight:(BOOL)highlight limit:(NSUInteger)limit markMatches:(BOOL)markMatches 4428{ 4429 return [self countMatchesForText:string options:(caseFlag ? 0 : WebFindOptionsCaseInsensitive) highlight:highlight limit:limit markMatches:markMatches]; 4430} 4431 4432- (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag startInSelection:(BOOL)startInSelection 4433{ 4434 return [self findString:string options:((forward ? 0 : WebFindOptionsBackwards) | (caseFlag ? 0 : WebFindOptionsCaseInsensitive) | (wrapFlag ? WebFindOptionsWrapAround : 0) | (startInSelection ? WebFindOptionsStartInSelection : 0))]; 4435} 4436 4437+ (void)_setLoadResourcesSerially:(BOOL)serialize 4438{ 4439 WebPlatformStrategies::initializeIfNecessary(); 4440 resourceLoadScheduler()->setSerialLoadingEnabled(serialize); 4441} 4442 4443+ (BOOL)_HTTPPipeliningEnabled 4444{ 4445 return ResourceRequest::httpPipeliningEnabled(); 4446} 4447 4448+ (void)_setHTTPPipeliningEnabled:(BOOL)enabled 4449{ 4450 ResourceRequest::setHTTPPipeliningEnabled(enabled); 4451} 4452 4453#if PLATFORM(IOS) 4454- (WebFixedPositionContent*)_fixedPositionContent 4455{ 4456 return _private ? _private->_fixedPositionContent : nil; 4457} 4458 4459- (void)_documentScaleChanged 4460{ 4461 if (WebNodeHighlight *currentHighlight = [self currentNodeHighlight]) 4462 [currentHighlight setNeedsDisplay]; 4463 4464 if (_private->indicateLayer) { 4465 [_private->indicateLayer setNeedsLayout]; 4466 [_private->indicateLayer setNeedsDisplay]; 4467 } 4468} 4469 4470- (BOOL)_wantsTelephoneNumberParsing 4471{ 4472 if (!_private->page) 4473 return NO; 4474 return _private->page->settings().telephoneNumberParsingEnabled(); 4475} 4476 4477- (void)_setWantsTelephoneNumberParsing:(BOOL)flag 4478{ 4479 if (_private->page) 4480 _private->page->settings().setTelephoneNumberParsingEnabled(flag); 4481} 4482 4483- (BOOL)_webGLEnabled 4484{ 4485 if (!_private->page) 4486 return NO; 4487 return _private->page->settings().webGLEnabled(); 4488} 4489 4490- (void)_setWebGLEnabled:(BOOL)enabled 4491{ 4492 if (_private->page) 4493 _private->page->settings().setWebGLEnabled(enabled); 4494} 4495 4496+ (void)_setTileCacheLayerPoolCapacity:(unsigned)capacity 4497{ 4498 LegacyTileCache::setLayerPoolCapacity(capacity); 4499} 4500#endif // PLATFORM(IOS) 4501 4502- (void)_setSourceApplicationAuditData:(NSData *)sourceApplicationAuditData 4503{ 4504 if (_private->sourceApplicationAuditData == sourceApplicationAuditData) 4505 return; 4506 4507 _private->sourceApplicationAuditData = adoptNS([sourceApplicationAuditData copy]); 4508} 4509 4510- (NSData *)_sourceApplicationAuditData 4511{ 4512 return _private->sourceApplicationAuditData.get(); 4513} 4514 4515- (void)_setFontFallbackPrefersPictographs:(BOOL)flag 4516{ 4517 if (_private->page) 4518 _private->page->settings().setFontFallbackPrefersPictographs(flag); 4519} 4520 4521@end 4522 4523@implementation _WebSafeForwarder 4524 4525// Used to send messages to delegates that implement informal protocols. 4526 4527- (instancetype)initWithTarget:(id)t defaultTarget:(id)dt 4528{ 4529 self = [super init]; 4530 if (!self) 4531 return nil; 4532 target = t; // Non retained. 4533 defaultTarget = dt; 4534 return self; 4535} 4536 4537#if PLATFORM(IOS) 4538- (id)asyncForwarder 4539{ 4540 dispatch_once(&asyncForwarderPred, ^{ 4541 asyncForwarder = [[_WebSafeAsyncForwarder alloc] initWithForwarder:self]; 4542 }); 4543 return asyncForwarder; 4544} 4545 4546- (void)dealloc 4547{ 4548 [asyncForwarder release]; 4549 [super dealloc]; 4550} 4551 4552- (void)clearTarget 4553{ 4554 target = nil; 4555} 4556#endif 4557 4558- (void)forwardInvocation:(NSInvocation *)invocation 4559{ 4560#if PLATFORM(IOS) 4561 if (WebThreadIsCurrent()) { 4562 [invocation retainArguments]; 4563 WebThreadCallDelegate(invocation); 4564 return; 4565 } 4566#endif 4567 if ([target respondsToSelector:[invocation selector]]) { 4568 @try { 4569 [invocation invokeWithTarget:target]; 4570 } @catch(id exception) { 4571 ReportDiscardedDelegateException([invocation selector], exception); 4572 } 4573 return; 4574 } 4575 4576 if ([defaultTarget respondsToSelector:[invocation selector]]) 4577 [invocation invokeWithTarget:defaultTarget]; 4578 4579 // Do nothing quietly if method not implemented. 4580} 4581 4582#if PLATFORM(IOS) 4583- (BOOL)respondsToSelector:(SEL)aSelector 4584{ 4585 return [defaultTarget respondsToSelector:aSelector]; 4586} 4587#endif 4588 4589- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector 4590{ 4591 return [defaultTarget methodSignatureForSelector:aSelector]; 4592} 4593 4594@end 4595 4596#if PLATFORM(IOS) 4597@implementation _WebSafeAsyncForwarder 4598 4599- (id)initWithForwarder:(_WebSafeForwarder *)forwarder 4600{ 4601 if (!(self = [super init])) 4602 return nil; 4603 _forwarder = forwarder; 4604 return self; 4605} 4606 4607- (void)forwardInvocation:(NSInvocation *)invocation 4608{ 4609 // Store _forwarder in an ivar so it is retained by the block. 4610 _WebSafeForwarder *forwarder = _forwarder; 4611 if (WebThreadIsCurrent()) { 4612 [invocation retainArguments]; 4613 dispatch_async(dispatch_get_main_queue(), ^{ 4614 [forwarder forwardInvocation:invocation]; 4615 }); 4616 } else 4617 [forwarder forwardInvocation:invocation]; 4618} 4619 4620- (BOOL)respondsToSelector:(SEL)aSelector 4621{ 4622 return [_forwarder respondsToSelector:aSelector]; 4623} 4624 4625- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector 4626{ 4627 return [_forwarder methodSignatureForSelector:aSelector]; 4628} 4629 4630@end 4631#endif 4632 4633@implementation WebView 4634 4635+ (void)initialize 4636{ 4637 static BOOL initialized = NO; 4638 if (initialized) 4639 return; 4640 initialized = YES; 4641 4642 InitWebCoreSystemInterface(); 4643#if !PLATFORM(IOS) 4644 JSC::initializeThreading(); 4645 WTF::initializeMainThreadToProcessMainThread(); 4646 RunLoop::initializeMainRunLoop(); 4647#endif 4648 4649#if !PLATFORM(IOS) 4650 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_applicationWillTerminate) name:NSApplicationWillTerminateNotification object:NSApp]; 4651#endif 4652 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_cacheModelChangedNotification:) name:WebPreferencesCacheModelChangedInternalNotification object:nil]; 4653 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesRemovedNotification:) name:WebPreferencesRemovedNotification object:nil]; 4654 4655 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 4656 4657#if PLATFORM(IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 4658 [defaults registerDefaults:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:WebKitKerningAndLigaturesEnabledByDefaultDefaultsKey]]; 4659#endif 4660 4661#if PLATFORM(IOS) 4662 continuousSpellCheckingEnabled = NO; 4663#endif 4664 4665#if !PLATFORM(IOS) 4666 continuousSpellCheckingEnabled = [defaults boolForKey:WebContinuousSpellCheckingEnabled]; 4667 grammarCheckingEnabled = [defaults boolForKey:WebGrammarCheckingEnabled]; 4668#endif 4669 4670 Font::setDefaultTypesettingFeatures([defaults boolForKey:WebKitKerningAndLigaturesEnabledByDefaultDefaultsKey] ? Kerning | Ligatures : 0); 4671 4672#if !PLATFORM(IOS) 4673 automaticQuoteSubstitutionEnabled = [self _shouldAutomaticQuoteSubstitutionBeEnabled]; 4674 automaticLinkDetectionEnabled = [defaults boolForKey:WebAutomaticLinkDetectionEnabled]; 4675 automaticDashSubstitutionEnabled = [self _shouldAutomaticDashSubstitutionBeEnabled]; 4676 automaticTextReplacementEnabled = [self _shouldAutomaticTextReplacementBeEnabled]; 4677 automaticSpellingCorrectionEnabled = [self _shouldAutomaticSpellingCorrectionBeEnabled]; 4678 4679 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_didChangeAutomaticTextReplacementEnabled:) 4680 name:NSSpellCheckerDidChangeAutomaticTextReplacementNotification object:nil]; 4681 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_didChangeAutomaticSpellingCorrectionEnabled:) 4682 name:NSSpellCheckerDidChangeAutomaticSpellingCorrectionNotification object:nil]; 4683 4684#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 4685 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_didChangeAutomaticQuoteSubstitutionEnabled:) 4686 name:NSSpellCheckerDidChangeAutomaticQuoteSubstitutionNotification object:nil]; 4687 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_didChangeAutomaticDashSubstitutionEnabled:) 4688 name:NSSpellCheckerDidChangeAutomaticDashSubstitutionNotification object:nil]; 4689#endif 4690#endif 4691} 4692 4693#if !PLATFORM(IOS) 4694+ (BOOL)_shouldAutomaticTextReplacementBeEnabled 4695{ 4696 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 4697 if (![defaults objectForKey:WebAutomaticTextReplacementEnabled]) 4698 return [NSSpellChecker isAutomaticTextReplacementEnabled]; 4699 return [defaults boolForKey:WebAutomaticTextReplacementEnabled]; 4700} 4701 4702+ (void)_didChangeAutomaticTextReplacementEnabled:(NSNotification *)notification 4703{ 4704 automaticTextReplacementEnabled = [self _shouldAutomaticTextReplacementBeEnabled]; 4705 [[NSSpellChecker sharedSpellChecker] updatePanels]; 4706} 4707 4708+ (BOOL)_shouldAutomaticSpellingCorrectionBeEnabled 4709{ 4710 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 4711 if (![defaults objectForKey:WebAutomaticSpellingCorrectionEnabled]) 4712 return [NSSpellChecker isAutomaticTextReplacementEnabled]; 4713 return [defaults boolForKey:WebAutomaticSpellingCorrectionEnabled]; 4714} 4715 4716+ (void)_didChangeAutomaticSpellingCorrectionEnabled:(NSNotification *)notification 4717{ 4718 automaticSpellingCorrectionEnabled = [self _shouldAutomaticSpellingCorrectionBeEnabled]; 4719 [[NSSpellChecker sharedSpellChecker] updatePanels]; 4720} 4721 4722+ (BOOL)_shouldAutomaticQuoteSubstitutionBeEnabled 4723{ 4724 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 4725#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 4726 if (![defaults objectForKey:WebAutomaticQuoteSubstitutionEnabled]) 4727 return [NSSpellChecker isAutomaticQuoteSubstitutionEnabled]; 4728#endif 4729 return [defaults boolForKey:WebAutomaticQuoteSubstitutionEnabled]; 4730} 4731 4732+ (BOOL)_shouldAutomaticDashSubstitutionBeEnabled 4733{ 4734 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 4735#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 4736 if (![defaults objectForKey:WebAutomaticDashSubstitutionEnabled]) 4737 return [NSSpellChecker isAutomaticDashSubstitutionEnabled]; 4738#endif 4739 return [defaults boolForKey:WebAutomaticDashSubstitutionEnabled]; 4740} 4741 4742#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 4743+ (void)_didChangeAutomaticQuoteSubstitutionEnabled:(NSNotification *)notification 4744{ 4745 automaticQuoteSubstitutionEnabled = [self _shouldAutomaticQuoteSubstitutionBeEnabled]; 4746 [[NSSpellChecker sharedSpellChecker] updatePanels]; 4747} 4748 4749+ (void)_didChangeAutomaticDashSubstitutionEnabled:(NSNotification *)notification 4750{ 4751 automaticDashSubstitutionEnabled = [self _shouldAutomaticDashSubstitutionBeEnabled]; 4752 [[NSSpellChecker sharedSpellChecker] updatePanels]; 4753} 4754#endif 4755 4756+ (void)_applicationWillTerminate 4757{ 4758 applicationIsTerminating = YES; 4759 4760 if (fastDocumentTeardownEnabled()) 4761 [self closeAllWebViews]; 4762 4763 if (!pluginDatabaseClientCount) 4764 [WebPluginDatabase closeSharedDatabase]; 4765 4766 PageGroup::closeLocalStorage(); 4767} 4768#endif // !PLATFORM(IOS) 4769 4770+ (BOOL)_canShowMIMEType:(NSString *)MIMEType allowingPlugins:(BOOL)allowPlugins 4771{ 4772 return [self _viewClass:nil andRepresentationClass:nil forMIMEType:MIMEType allowingPlugins:allowPlugins]; 4773} 4774 4775+ (BOOL)canShowMIMEType:(NSString *)MIMEType 4776{ 4777 return [self _canShowMIMEType:MIMEType allowingPlugins:YES]; 4778} 4779 4780- (BOOL)_canShowMIMEType:(NSString *)MIMEType 4781{ 4782 return [[self class] _canShowMIMEType:MIMEType allowingPlugins:[_private->preferences arePlugInsEnabled]]; 4783} 4784 4785- (WebBasePluginPackage *)_pluginForMIMEType:(NSString *)MIMEType 4786{ 4787 if (![_private->preferences arePlugInsEnabled]) 4788 return nil; 4789 4790 WebBasePluginPackage *pluginPackage = [[WebPluginDatabase sharedDatabase] pluginForMIMEType:MIMEType]; 4791 if (pluginPackage) 4792 return pluginPackage; 4793 4794#if !PLATFORM(IOS) 4795 if (_private->pluginDatabase) 4796 return [_private->pluginDatabase pluginForMIMEType:MIMEType]; 4797#endif 4798 4799 return nil; 4800} 4801 4802- (WebBasePluginPackage *)_pluginForExtension:(NSString *)extension 4803{ 4804 if (![_private->preferences arePlugInsEnabled]) 4805 return nil; 4806 4807 WebBasePluginPackage *pluginPackage = [[WebPluginDatabase sharedDatabase] pluginForExtension:extension]; 4808 if (pluginPackage) 4809 return pluginPackage; 4810 4811#if !PLATFORM(IOS) 4812 if (_private->pluginDatabase) 4813 return [_private->pluginDatabase pluginForExtension:extension]; 4814#endif 4815 4816 return nil; 4817} 4818 4819#if !PLATFORM(IOS) 4820- (void)addPluginInstanceView:(NSView *)view 4821{ 4822 if (!_private->pluginDatabase) 4823 _private->pluginDatabase = [[WebPluginDatabase alloc] init]; 4824 [_private->pluginDatabase addPluginInstanceView:view]; 4825} 4826 4827- (void)removePluginInstanceView:(NSView *)view 4828{ 4829 if (_private->pluginDatabase) 4830 [_private->pluginDatabase removePluginInstanceView:view]; 4831} 4832 4833- (void)removePluginInstanceViewsFor:(WebFrame*)webFrame 4834{ 4835 if (_private->pluginDatabase) 4836 [_private->pluginDatabase removePluginInstanceViewsFor:webFrame]; 4837} 4838#endif 4839 4840- (BOOL)_isMIMETypeRegisteredAsPlugin:(NSString *)MIMEType 4841{ 4842 if (![_private->preferences arePlugInsEnabled]) 4843 return NO; 4844 4845 if ([[WebPluginDatabase sharedDatabase] isMIMETypeRegistered:MIMEType]) 4846 return YES; 4847 4848#if !PLATFORM(IOS) 4849 if (_private->pluginDatabase && [_private->pluginDatabase isMIMETypeRegistered:MIMEType]) 4850 return YES; 4851#endif 4852 4853 return NO; 4854} 4855 4856+ (BOOL)canShowMIMETypeAsHTML:(NSString *)MIMEType 4857{ 4858#if PLATFORM(IOS) 4859 // FIXME: <rdar://problem/7961656> +[WebView canShowMIMETypeAsHTML:] regressed significantly in iOS 4.0 4860 // Fast path for the common case to avoid creating the MIME type registry. 4861 if ([MIMEType isEqualToString:@"text/html"]) 4862 return YES; 4863#endif 4864 return [WebFrameView _canShowMIMETypeAsHTML:MIMEType]; 4865} 4866 4867+ (NSArray *)MIMETypesShownAsHTML 4868{ 4869 NSMutableDictionary *viewTypes = [WebFrameView _viewTypesAllowImageTypeOmission:YES]; 4870 NSEnumerator *enumerator = [viewTypes keyEnumerator]; 4871 id key; 4872 NSMutableArray *array = [[[NSMutableArray alloc] init] autorelease]; 4873 4874 while ((key = [enumerator nextObject])) { 4875 if ([viewTypes objectForKey:key] == [WebHTMLView class]) 4876 [array addObject:key]; 4877 } 4878 4879 return array; 4880} 4881 4882+ (void)setMIMETypesShownAsHTML:(NSArray *)MIMETypes 4883{ 4884 NSDictionary *viewTypes = [[WebFrameView _viewTypesAllowImageTypeOmission:YES] copy]; 4885 NSEnumerator *enumerator = [viewTypes keyEnumerator]; 4886 id key; 4887 while ((key = [enumerator nextObject])) { 4888 if ([viewTypes objectForKey:key] == [WebHTMLView class]) 4889 [WebView _unregisterViewClassAndRepresentationClassForMIMEType:key]; 4890 } 4891 4892 int i, count = [MIMETypes count]; 4893 for (i = 0; i < count; i++) { 4894 [WebView registerViewClass:[WebHTMLView class] 4895 representationClass:[WebHTMLRepresentation class] 4896 forMIMEType:[MIMETypes objectAtIndex:i]]; 4897 } 4898 [viewTypes release]; 4899} 4900 4901#if !PLATFORM(IOS) 4902+ (NSURL *)URLFromPasteboard:(NSPasteboard *)pasteboard 4903{ 4904 return [pasteboard _web_bestURL]; 4905} 4906 4907+ (NSString *)URLTitleFromPasteboard:(NSPasteboard *)pasteboard 4908{ 4909 return [pasteboard stringForType:WebURLNamePboardType]; 4910} 4911#endif 4912 4913+ (void)registerURLSchemeAsLocal:(NSString *)protocol 4914{ 4915 SchemeRegistry::registerURLSchemeAsLocal(protocol); 4916} 4917 4918- (id)_initWithArguments:(NSDictionary *) arguments 4919{ 4920#if !PLATFORM(IOS) 4921 NSCoder *decoder = [arguments objectForKey:@"decoder"]; 4922 if (decoder) { 4923 self = [self initWithCoder:decoder]; 4924 } else { 4925#endif 4926 ASSERT([arguments objectForKey:@"frame"]); 4927 NSValue *frameValue = [arguments objectForKey:@"frame"]; 4928 NSRect frame = (frameValue ? [frameValue rectValue] : NSZeroRect); 4929 NSString *frameName = [arguments objectForKey:@"frameName"]; 4930 NSString *groupName = [arguments objectForKey:@"groupName"]; 4931 self = [self initWithFrame:frame frameName:frameName groupName:groupName]; 4932#if !PLATFORM(IOS) 4933 } 4934#endif 4935 4936 return self; 4937} 4938 4939#if !PLATFORM(IOS) 4940static bool clientNeedsWebViewInitThreadWorkaround() 4941{ 4942 if (WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_WEBVIEW_INIT_THREAD_WORKAROUND)) 4943 return false; 4944 4945 NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier]; 4946 4947 // Installer. 4948 if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.installer"]) 4949 return true; 4950 4951 // Automator. 4952 if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.Automator"]) 4953 return true; 4954 4955 // Automator Runner. 4956 if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.AutomatorRunner"]) 4957 return true; 4958 4959 // Automator workflows. 4960 if ([bundleIdentifier _webkit_hasCaseInsensitivePrefix:@"com.apple.Automator."]) 4961 return true; 4962 4963 return false; 4964} 4965 4966static bool needsWebViewInitThreadWorkaround() 4967{ 4968 static bool isOldClient = clientNeedsWebViewInitThreadWorkaround(); 4969 return isOldClient && !pthread_main_np(); 4970} 4971#endif // !PLATFORM(IOS) 4972 4973- (instancetype)initWithFrame:(NSRect)f 4974{ 4975 return [self initWithFrame:f frameName:nil groupName:nil]; 4976} 4977 4978- (instancetype)initWithFrame:(NSRect)f frameName:(NSString *)frameName groupName:(NSString *)groupName 4979{ 4980#if !PLATFORM(IOS) 4981 if (needsWebViewInitThreadWorkaround()) 4982 return [[self _webkit_invokeOnMainThread] initWithFrame:f frameName:frameName groupName:groupName]; 4983#endif 4984 4985 WebCoreThreadViolationCheckRoundTwo(); 4986 return [self _initWithFrame:f frameName:frameName groupName:groupName]; 4987} 4988 4989#if !PLATFORM(IOS) 4990- (instancetype)initWithCoder:(NSCoder *)decoder 4991{ 4992 if (needsWebViewInitThreadWorkaround()) 4993 return [[self _webkit_invokeOnMainThread] initWithCoder:decoder]; 4994 4995 WebCoreThreadViolationCheckRoundTwo(); 4996 WebView *result = nil; 4997 4998 @try { 4999 NSString *frameName; 5000 NSString *groupName; 5001 WebPreferences *preferences; 5002 BOOL useBackForwardList = NO; 5003 BOOL allowsUndo = YES; 5004 5005 result = [super initWithCoder:decoder]; 5006 result->_private = [[WebViewPrivate alloc] init]; 5007 5008 // We don't want any of the archived subviews. The subviews will always 5009 // be created in _commonInitializationFrameName:groupName:. 5010 [[result subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)]; 5011 5012 if ([decoder allowsKeyedCoding]) { 5013 frameName = [decoder decodeObjectForKey:@"FrameName"]; 5014 groupName = [decoder decodeObjectForKey:@"GroupName"]; 5015 preferences = [decoder decodeObjectForKey:@"Preferences"]; 5016 useBackForwardList = [decoder decodeBoolForKey:@"UseBackForwardList"]; 5017 if ([decoder containsValueForKey:@"AllowsUndo"]) 5018 allowsUndo = [decoder decodeBoolForKey:@"AllowsUndo"]; 5019 } else { 5020 int version; 5021 [decoder decodeValueOfObjCType:@encode(int) at:&version]; 5022 frameName = [decoder decodeObject]; 5023 groupName = [decoder decodeObject]; 5024 preferences = [decoder decodeObject]; 5025 if (version > 1) 5026 [decoder decodeValuesOfObjCTypes:"c", &useBackForwardList]; 5027 // The allowsUndo field is no longer written out in encodeWithCoder, but since there are 5028 // version 3 NIBs that have this field encoded, we still need to read it in. 5029 if (version == 3) 5030 [decoder decodeValuesOfObjCTypes:"c", &allowsUndo]; 5031 } 5032 5033 if (![frameName isKindOfClass:[NSString class]]) 5034 frameName = nil; 5035 if (![groupName isKindOfClass:[NSString class]]) 5036 groupName = nil; 5037 if (![preferences isKindOfClass:[WebPreferences class]]) 5038 preferences = nil; 5039 5040 LOG(Encoding, "FrameName = %@, GroupName = %@, useBackForwardList = %d\n", frameName, groupName, (int)useBackForwardList); 5041 [result _commonInitializationWithFrameName:frameName groupName:groupName]; 5042 static_cast<BackForwardList*>([result page]->backForward().client())->setEnabled(useBackForwardList); 5043 result->_private->allowsUndo = allowsUndo; 5044 if (preferences) 5045 [result setPreferences:preferences]; 5046 } @catch (NSException *localException) { 5047 result = nil; 5048 [self release]; 5049 } 5050 5051 return result; 5052} 5053 5054- (void)encodeWithCoder:(NSCoder *)encoder 5055{ 5056 // Set asside the subviews before we archive. We don't want to archive any subviews. 5057 // The subviews will always be created in _commonInitializationFrameName:groupName:. 5058 id originalSubviews = _subviews; 5059 _subviews = nil; 5060 5061 [super encodeWithCoder:encoder]; 5062 5063 // Restore the subviews we set aside. 5064 _subviews = originalSubviews; 5065 5066 BOOL useBackForwardList = _private->page && static_cast<BackForwardList*>(_private->page->backForward().client())->enabled(); 5067 if ([encoder allowsKeyedCoding]) { 5068 [encoder encodeObject:[[self mainFrame] name] forKey:@"FrameName"]; 5069 [encoder encodeObject:[self groupName] forKey:@"GroupName"]; 5070 [encoder encodeObject:[self preferences] forKey:@"Preferences"]; 5071 [encoder encodeBool:useBackForwardList forKey:@"UseBackForwardList"]; 5072 [encoder encodeBool:_private->allowsUndo forKey:@"AllowsUndo"]; 5073 } else { 5074 int version = WebViewVersion; 5075 [encoder encodeValueOfObjCType:@encode(int) at:&version]; 5076 [encoder encodeObject:[[self mainFrame] name]]; 5077 [encoder encodeObject:[self groupName]]; 5078 [encoder encodeObject:[self preferences]]; 5079 [encoder encodeValuesOfObjCTypes:"c", &useBackForwardList]; 5080 // DO NOT encode any new fields here, doing so will break older WebKit releases. 5081 } 5082 5083 LOG(Encoding, "FrameName = %@, GroupName = %@, useBackForwardList = %d\n", [[self mainFrame] name], [self groupName], (int)useBackForwardList); 5084} 5085#endif // !PLATFORM(IOS) 5086 5087- (void)dealloc 5088{ 5089 if (WebCoreObjCScheduleDeallocateOnMainThread([WebView class], self)) 5090 return; 5091 5092#if PLATFORM(IOS) 5093 if (_private) 5094 [_private->_geolocationProvider stopTrackingWebView:self]; 5095#endif 5096 5097 // call close to ensure we tear-down completely 5098 // this maintains our old behavior for existing applications 5099 [self close]; 5100 5101 if ([[self class] shouldIncludeInWebKitStatistics]) 5102 --WebViewCount; 5103 5104#if !PLATFORM(IOS) 5105 if ([self _needsFrameLoadDelegateRetainQuirk]) 5106 [_private->frameLoadDelegate release]; 5107#endif 5108 5109 [_private release]; 5110 // [super dealloc] can end up dispatching against _private (3466082) 5111 _private = nil; 5112 5113 [super dealloc]; 5114} 5115 5116- (void)finalize 5117{ 5118 ASSERT(_private->closed); 5119 5120 --WebViewCount; 5121 5122 [super finalize]; 5123} 5124 5125- (void)close 5126{ 5127 // _close existed first, and some clients might be calling or overriding it, so call through. 5128 [self _close]; 5129 5130#if PLATFORM(IOS) 5131 if (_private->layerFlushController) { 5132 _private->layerFlushController->invalidate(); 5133 _private->layerFlushController = nullptr; 5134 } 5135#endif 5136} 5137 5138- (void)setShouldCloseWithWindow:(BOOL)close 5139{ 5140 _private->shouldCloseWithWindow = close; 5141} 5142 5143- (BOOL)shouldCloseWithWindow 5144{ 5145 return _private->shouldCloseWithWindow; 5146} 5147 5148#if !PLATFORM(IOS) 5149// FIXME: Use AppKit constants for these when they are available. 5150static NSString * const windowDidChangeBackingPropertiesNotification = @"NSWindowDidChangeBackingPropertiesNotification"; 5151static NSString * const backingPropertyOldScaleFactorKey = @"NSBackingPropertyOldScaleFactorKey"; 5152 5153- (void)addWindowObserversForWindow:(NSWindow *)window 5154{ 5155 if (window) { 5156 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowKeyStateChanged:) 5157 name:NSWindowDidBecomeKeyNotification object:window]; 5158 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowKeyStateChanged:) 5159 name:NSWindowDidResignKeyNotification object:window]; 5160 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillOrderOnScreen:) 5161 name:WKWindowWillOrderOnScreenNotification() object:window]; 5162 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillOrderOffScreen:) 5163 name:WKWindowWillOrderOffScreenNotification() object:window]; 5164 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowDidChangeBackingProperties:) 5165 name:windowDidChangeBackingPropertiesNotification object:window]; 5166 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowDidChangeScreen:) 5167 name:NSWindowDidChangeScreenNotification object:window]; 5168 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowVisibilityChanged:) 5169 name:NSWindowDidMiniaturizeNotification object:window]; 5170 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowVisibilityChanged:) 5171 name:NSWindowDidDeminiaturizeNotification object:window]; 5172 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowVisibilityChanged:) 5173 name:@"NSWindowDidOrderOffScreenNotification" object:window]; 5174 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowVisibilityChanged:) 5175 name:@"_NSWindowDidBecomeVisible" object:window]; 5176 } 5177} 5178 5179- (void)removeWindowObservers 5180{ 5181 NSWindow *window = [self window]; 5182 if (window) { 5183 [[NSNotificationCenter defaultCenter] removeObserver:self 5184 name:NSWindowDidBecomeKeyNotification object:window]; 5185 [[NSNotificationCenter defaultCenter] removeObserver:self 5186 name:NSWindowDidResignKeyNotification object:window]; 5187 [[NSNotificationCenter defaultCenter] removeObserver:self 5188 name:WKWindowWillOrderOnScreenNotification() object:window]; 5189 [[NSNotificationCenter defaultCenter] removeObserver:self 5190 name:WKWindowWillOrderOffScreenNotification() object:window]; 5191 [[NSNotificationCenter defaultCenter] removeObserver:self 5192 name:windowDidChangeBackingPropertiesNotification object:window]; 5193 [[NSNotificationCenter defaultCenter] removeObserver:self 5194 name:NSWindowDidChangeScreenNotification object:window]; 5195 [[NSNotificationCenter defaultCenter] removeObserver:self 5196 name:NSWindowDidMiniaturizeNotification object:window]; 5197 [[NSNotificationCenter defaultCenter] removeObserver:self 5198 name:NSWindowDidDeminiaturizeNotification object:window]; 5199 [[NSNotificationCenter defaultCenter] removeObserver:self 5200 name:@"NSWindowDidOrderOffScreenNotification" object:window]; 5201 [[NSNotificationCenter defaultCenter] removeObserver:self 5202 name:@"_NSWindowDidBecomeVisible" object:window]; 5203 } 5204} 5205 5206- (void)viewWillMoveToWindow:(NSWindow *)window 5207{ 5208 // Don't do anything if the WebView isn't initialized. 5209 // This happens when decoding a WebView in a nib. 5210 // FIXME: What sets up the observer of NSWindowWillCloseNotification in this case? 5211 if (!_private || _private->closed) 5212 return; 5213 5214 if ([self window] && [self window] != [self hostWindow]) 5215 [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowWillCloseNotification object:[self window]]; 5216 5217 if (window) { 5218 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillClose:) name:NSWindowWillCloseNotification object:window]; 5219 5220 // Ensure that we will receive the events that WebHTMLView (at least) needs. 5221 // The following are expensive enough that we don't want to call them over 5222 // and over, so do them when we move into a window. 5223 [window setAcceptsMouseMovedEvents:YES]; 5224 WKSetNSWindowShouldPostEventNotifications(window, YES); 5225 } else { 5226 _private->page->setCanStartMedia(false); 5227 _private->page->setIsInWindow(false); 5228 } 5229 5230 if (window != [self window]) { 5231 [self removeWindowObservers]; 5232 [self addWindowObserversForWindow:window]; 5233 } 5234} 5235#endif // !PLATFORM(IOS) 5236 5237- (void)viewDidMoveToWindow 5238{ 5239 // Don't do anything if we aren't initialized. This happens 5240 // when decoding a WebView. When WebViews are decoded their subviews 5241 // are created by initWithCoder: and so won't be normally 5242 // initialized. The stub views are discarded by WebView. 5243 if (!_private || _private->closed) 5244 return; 5245 5246 if ([self window]) { 5247 _private->page->setCanStartMedia(true); 5248 _private->page->setIsInWindow(true); 5249 5250#if PLATFORM(IOS) 5251 WebPreferences *preferences = [self preferences]; 5252 NSWindow *window = [self window]; 5253 [window setTileBordersVisible:[preferences showDebugBorders]]; 5254 [window setTilePaintCountsVisible:[preferences showRepaintCounter]]; 5255 [window setAcceleratedDrawingEnabled:[preferences acceleratedDrawingEnabled]]; 5256#endif 5257 } 5258#if PLATFORM(IOS) 5259 else 5260 [_private->fullscreenController requestHideAndExitFullscreen]; 5261#endif 5262 5263#if !PLATFORM(IOS) 5264 _private->page->setDeviceScaleFactor([self _deviceScaleFactor]); 5265#endif 5266 5267 [self _updateActiveState]; 5268 [self _updateVisibilityState]; 5269} 5270 5271#if !PLATFORM(IOS) 5272- (void)doWindowDidChangeScreen 5273{ 5274 if (_private && _private->page) 5275 _private->page->chrome().windowScreenDidChange((PlatformDisplayID)[[[[[self window] screen] deviceDescription] objectForKey:@"NSScreenNumber"] intValue]); 5276} 5277 5278- (void)_windowChangedKeyState 5279{ 5280 [self _updateActiveState]; 5281 [super _windowChangedKeyState]; 5282} 5283 5284- (void)windowKeyStateChanged:(NSNotification *)notification 5285{ 5286 [self _updateActiveState]; 5287} 5288 5289- (void)viewDidHide 5290{ 5291 [self _updateVisibilityState]; 5292} 5293 5294- (void)viewDidUnhide 5295{ 5296 [self _updateVisibilityState]; 5297} 5298 5299- (void)_windowWillOrderOnScreen:(NSNotification *)notification 5300{ 5301 if (![self shouldUpdateWhileOffscreen]) 5302 [self setNeedsDisplay:YES]; 5303 5304 // Send a change screen to make sure the initial displayID is set 5305 [self doWindowDidChangeScreen]; 5306 5307 if (_private && _private->page) { 5308 _private->page->resumeScriptedAnimations(); 5309 _private->page->setIsVisible(true); 5310 } 5311} 5312 5313- (void)_windowDidChangeScreen:(NSNotification *)notification 5314{ 5315 [self doWindowDidChangeScreen]; 5316} 5317 5318- (void)_windowWillOrderOffScreen:(NSNotification *)notification 5319{ 5320 if (_private && _private->page) { 5321 _private->page->suspendScriptedAnimations(); 5322 _private->page->setIsVisible(false); 5323 } 5324} 5325 5326- (void)_windowVisibilityChanged:(NSNotification *)notification 5327{ 5328 [self _updateVisibilityState]; 5329} 5330 5331- (void)_windowWillClose:(NSNotification *)notification 5332{ 5333 if ([self shouldCloseWithWindow] && ([self window] == [self hostWindow] || ([self window] && ![self hostWindow]) || (![self window] && [self hostWindow]))) 5334 [self close]; 5335} 5336 5337- (void)_windowDidChangeBackingProperties:(NSNotification *)notification 5338{ 5339 CGFloat oldBackingScaleFactor = [[notification.userInfo objectForKey:backingPropertyOldScaleFactorKey] doubleValue]; 5340 CGFloat newBackingScaleFactor = [self _deviceScaleFactor]; 5341 if (oldBackingScaleFactor == newBackingScaleFactor) 5342 return; 5343 5344 _private->page->setDeviceScaleFactor(newBackingScaleFactor); 5345} 5346#else 5347- (void)_wakWindowScreenScaleChanged:(NSNotification *)notification 5348{ 5349 [self _updateScreenScaleFromWindow]; 5350} 5351 5352- (void)_wakWindowVisibilityChanged:(NSNotification *)notification 5353{ 5354 if ([notification object] == [self window]) 5355 [self _updateVisibilityState]; 5356} 5357 5358- (void)_updateScreenScaleFromWindow 5359{ 5360 float scaleFactor = 1.0f; 5361 if (WAKWindow *window = [self window]) 5362 scaleFactor = [window screenScale]; 5363 else 5364 scaleFactor = WKGetScreenScaleFactor(); 5365 5366 _private->page->setDeviceScaleFactor(scaleFactor); 5367} 5368#endif // PLATFORM(IOS) 5369 5370- (void)setPreferences:(WebPreferences *)prefs 5371{ 5372 if (!prefs) 5373 prefs = [WebPreferences standardPreferences]; 5374 5375 if (_private->preferences == prefs) 5376 return; 5377 5378 [prefs willAddToWebView]; 5379 5380 WebPreferences *oldPrefs = _private->preferences; 5381 5382 [[NSNotificationCenter defaultCenter] removeObserver:self name:WebPreferencesChangedInternalNotification object:[self preferences]]; 5383 [WebPreferences _removeReferenceForIdentifier:[oldPrefs identifier]]; 5384 5385 _private->preferences = [prefs retain]; 5386 5387 // After registering for the notification, post it so the WebCore settings update. 5388 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:) 5389 name:WebPreferencesChangedInternalNotification object:[self preferences]]; 5390 [self _preferencesChanged:[self preferences]]; 5391 [[self preferences] _postPreferencesChangedAPINotification]; 5392 5393 [oldPrefs didRemoveFromWebView]; 5394 [oldPrefs release]; 5395} 5396 5397- (WebPreferences *)preferences 5398{ 5399 return _private->preferences; 5400} 5401 5402- (void)setPreferencesIdentifier:(NSString *)anIdentifier 5403{ 5404 if (!_private->closed && ![anIdentifier isEqual:[[self preferences] identifier]]) { 5405 WebPreferences *prefs = [[WebPreferences alloc] initWithIdentifier:anIdentifier]; 5406 [self setPreferences:prefs]; 5407 [prefs release]; 5408 } 5409} 5410 5411- (NSString *)preferencesIdentifier 5412{ 5413 return [[self preferences] identifier]; 5414} 5415 5416 5417- (void)setUIDelegate:delegate 5418{ 5419 _private->UIDelegate = delegate; 5420#if PLATFORM(IOS) 5421 [_private->UIDelegateForwarder clearTarget]; 5422#endif 5423 [_private->UIDelegateForwarder release]; 5424 _private->UIDelegateForwarder = nil; 5425} 5426 5427- (id)UIDelegate 5428{ 5429 return _private->UIDelegate; 5430} 5431 5432#if PLATFORM(IOS) 5433- (id)_resourceLoadDelegateForwarder 5434{ 5435 if (_private->closing) 5436 return nil; 5437 5438 if (!_private->resourceProgressDelegateForwarder) 5439 _private->resourceProgressDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:[self resourceLoadDelegate] defaultTarget:[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate]]; 5440 return _private->resourceProgressDelegateForwarder; 5441} 5442#endif 5443 5444- (void)setResourceLoadDelegate: delegate 5445{ 5446#if PLATFORM(IOS) 5447 [_private->resourceProgressDelegateForwarder clearTarget]; 5448 [_private->resourceProgressDelegateForwarder release]; 5449 _private->resourceProgressDelegateForwarder = nil; 5450#endif 5451 _private->resourceProgressDelegate = delegate; 5452 [self _cacheResourceLoadDelegateImplementations]; 5453} 5454 5455- (id)resourceLoadDelegate 5456{ 5457 return _private->resourceProgressDelegate; 5458} 5459 5460- (void)setDownloadDelegate: delegate 5461{ 5462 _private->downloadDelegate = delegate; 5463} 5464 5465 5466- (id)downloadDelegate 5467{ 5468 return _private->downloadDelegate; 5469} 5470 5471- (void)setPolicyDelegate:delegate 5472{ 5473 _private->policyDelegate = delegate; 5474#if PLATFORM(IOS) 5475 [_private->policyDelegateForwarder clearTarget]; 5476#endif 5477 [_private->policyDelegateForwarder release]; 5478 _private->policyDelegateForwarder = nil; 5479} 5480 5481- (id)policyDelegate 5482{ 5483 return _private->policyDelegate; 5484} 5485 5486#if PLATFORM(IOS) 5487- (id)_frameLoadDelegateForwarder 5488{ 5489 if (_private->closing) 5490 return nil; 5491 5492 if (!_private->frameLoadDelegateForwarder) 5493 _private->frameLoadDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:[self frameLoadDelegate] defaultTarget:[WebDefaultFrameLoadDelegate sharedFrameLoadDelegate]]; 5494 return _private->frameLoadDelegateForwarder; 5495} 5496#endif 5497 5498- (void)setFrameLoadDelegate:delegate 5499{ 5500 // <rdar://problem/6950660> - Due to some subtle WebKit changes - presumably to delegate callback behavior - we've 5501 // unconvered a latent bug in at least one WebKit app where the delegate wasn't properly retained by the app and 5502 // was dealloc'ed before being cleared. 5503 // This is an effort to keep such apps working for now. 5504#if !PLATFORM(IOS) 5505 if ([self _needsFrameLoadDelegateRetainQuirk]) { 5506 [delegate retain]; 5507 [_private->frameLoadDelegate release]; 5508 } 5509#else 5510 [_private->frameLoadDelegateForwarder clearTarget]; 5511 [_private->frameLoadDelegateForwarder release]; 5512 _private->frameLoadDelegateForwarder = nil; 5513#endif 5514 5515 _private->frameLoadDelegate = delegate; 5516 [self _cacheFrameLoadDelegateImplementations]; 5517 5518#if ENABLE(ICONDATABASE) 5519 // If this delegate wants callbacks for icons, fire up the icon database. 5520 if (_private->frameLoadDelegateImplementations.didReceiveIconForFrameFunc) 5521 [WebIconDatabase sharedIconDatabase]; 5522#endif 5523} 5524 5525- (id)frameLoadDelegate 5526{ 5527 return _private->frameLoadDelegate; 5528} 5529 5530- (WebFrame *)mainFrame 5531{ 5532 // This can be called in initialization, before _private has been set up (3465613) 5533 if (!_private || !_private->page) 5534 return nil; 5535 return kit(&_private->page->mainFrame()); 5536} 5537 5538- (WebFrame *)selectedFrame 5539{ 5540 // If the first responder is a view in our tree, we get the frame containing the first responder. 5541 // This is faster than searching the frame hierarchy, and will give us a result even in the case 5542 // where the focused frame doesn't actually contain a selection. 5543 WebFrame *focusedFrame = [self _focusedFrame]; 5544 if (focusedFrame) 5545 return focusedFrame; 5546 5547 // If the first responder is outside of our view tree, we search for a frame containing a selection. 5548 // There should be at most only one of these. 5549 return [[self mainFrame] _findFrameWithSelection]; 5550} 5551 5552- (WebBackForwardList *)backForwardList 5553{ 5554 if (!_private->page) 5555 return nil; 5556 BackForwardList* list = static_cast<BackForwardList*>(_private->page->backForward().client()); 5557 if (!list->enabled()) 5558 return nil; 5559 return kit(list); 5560} 5561 5562- (void)setMaintainsBackForwardList:(BOOL)flag 5563{ 5564 if (!_private->page) 5565 return; 5566 static_cast<BackForwardList*>(_private->page->backForward().client())->setEnabled(flag); 5567} 5568 5569- (BOOL)goBack 5570{ 5571 if (!_private->page) 5572 return NO; 5573 5574#if PLATFORM(IOS) 5575 if (WebThreadIsCurrent() || !WebThreadIsEnabled()) 5576#endif 5577 return _private->page->backForward().goBack(); 5578#if PLATFORM(IOS) 5579 WebThreadRun(^{ 5580 _private->page->backForward().goBack(); 5581 }); 5582 // FIXME: <rdar://problem/9157572> -[WebView goBack] and -goForward always return YES when called from the main thread 5583 return YES; 5584#endif 5585} 5586 5587- (BOOL)goForward 5588{ 5589 if (!_private->page) 5590 return NO; 5591 5592#if PLATFORM(IOS) 5593 if (WebThreadIsCurrent() || !WebThreadIsEnabled()) 5594#endif 5595 return _private->page->backForward().goForward(); 5596#if PLATFORM(IOS) 5597 WebThreadRun(^{ 5598 _private->page->backForward().goForward(); 5599 }); 5600 // FIXME: <rdar://problem/9157572> -[WebView goBack] and -goForward always return YES when called from the main thread 5601 return YES; 5602#endif 5603} 5604 5605- (BOOL)goToBackForwardItem:(WebHistoryItem *)item 5606{ 5607 if (!_private->page) 5608 return NO; 5609 5610 _private->page->goToItem(core(item), FrameLoadType::IndexedBackForward); 5611 return YES; 5612} 5613 5614- (void)setTextSizeMultiplier:(float)m 5615{ 5616 [self _setZoomMultiplier:m isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]]; 5617} 5618 5619- (float)textSizeMultiplier 5620{ 5621 return [self _realZoomMultiplierIsTextOnly] ? _private->zoomMultiplier : 1.0f; 5622} 5623 5624- (void)_setZoomMultiplier:(float)multiplier isTextOnly:(BOOL)isTextOnly 5625{ 5626 // NOTE: This has no visible effect when viewing a PDF (see <rdar://problem/4737380>) 5627 _private->zoomMultiplier = multiplier; 5628 _private->zoomsTextOnly = isTextOnly; 5629 5630 // FIXME: It might be nice to rework this code so that _private->zoomMultiplier doesn't exist 5631 // and instead the zoom factors stored in Frame are used. 5632 Frame* coreFrame = [self _mainCoreFrame]; 5633 if (coreFrame) { 5634 if (_private->zoomsTextOnly) 5635 coreFrame->setPageAndTextZoomFactors(1, multiplier); 5636 else 5637 coreFrame->setPageAndTextZoomFactors(multiplier, 1); 5638 } 5639} 5640 5641- (float)_zoomMultiplier:(BOOL)isTextOnly 5642{ 5643 if (isTextOnly != [self _realZoomMultiplierIsTextOnly]) 5644 return 1.0f; 5645 return _private->zoomMultiplier; 5646} 5647 5648- (float)_realZoomMultiplier 5649{ 5650 return _private->zoomMultiplier; 5651} 5652 5653- (BOOL)_realZoomMultiplierIsTextOnly 5654{ 5655 if (!_private->page) 5656 return NO; 5657 5658 return _private->zoomsTextOnly; 5659} 5660 5661#define MinimumZoomMultiplier 0.5f 5662#define MaximumZoomMultiplier 3.0f 5663#define ZoomMultiplierRatio 1.2f 5664 5665- (BOOL)_canZoomOut:(BOOL)isTextOnly 5666{ 5667 id docView = [[[self mainFrame] frameView] documentView]; 5668 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) { 5669 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView; 5670 return [zoomingDocView _canZoomOut]; 5671 } 5672 return [self _zoomMultiplier:isTextOnly] / ZoomMultiplierRatio > MinimumZoomMultiplier; 5673} 5674 5675 5676- (BOOL)_canZoomIn:(BOOL)isTextOnly 5677{ 5678 id docView = [[[self mainFrame] frameView] documentView]; 5679 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) { 5680 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView; 5681 return [zoomingDocView _canZoomIn]; 5682 } 5683 return [self _zoomMultiplier:isTextOnly] * ZoomMultiplierRatio < MaximumZoomMultiplier; 5684} 5685 5686- (IBAction)_zoomOut:(id)sender isTextOnly:(BOOL)isTextOnly 5687{ 5688 id docView = [[[self mainFrame] frameView] documentView]; 5689 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) { 5690 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView; 5691 return [zoomingDocView _zoomOut:sender]; 5692 } 5693 float newScale = [self _zoomMultiplier:isTextOnly] / ZoomMultiplierRatio; 5694 if (newScale > MinimumZoomMultiplier) 5695 [self _setZoomMultiplier:newScale isTextOnly:isTextOnly]; 5696} 5697 5698- (IBAction)_zoomIn:(id)sender isTextOnly:(BOOL)isTextOnly 5699{ 5700 id docView = [[[self mainFrame] frameView] documentView]; 5701 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) { 5702 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView; 5703 return [zoomingDocView _zoomIn:sender]; 5704 } 5705 float newScale = [self _zoomMultiplier:isTextOnly] * ZoomMultiplierRatio; 5706 if (newScale < MaximumZoomMultiplier) 5707 [self _setZoomMultiplier:newScale isTextOnly:isTextOnly]; 5708} 5709 5710- (BOOL)_canResetZoom:(BOOL)isTextOnly 5711{ 5712 id docView = [[[self mainFrame] frameView] documentView]; 5713 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) { 5714 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView; 5715 return [zoomingDocView _canResetZoom]; 5716 } 5717 return [self _zoomMultiplier:isTextOnly] != 1.0f; 5718} 5719 5720- (IBAction)_resetZoom:(id)sender isTextOnly:(BOOL)isTextOnly 5721{ 5722 id docView = [[[self mainFrame] frameView] documentView]; 5723 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) { 5724 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView; 5725 return [zoomingDocView _resetZoom:sender]; 5726 } 5727 if ([self _zoomMultiplier:isTextOnly] != 1.0f) 5728 [self _setZoomMultiplier:1.0f isTextOnly:isTextOnly]; 5729} 5730 5731- (void)setApplicationNameForUserAgent:(NSString *)applicationName 5732{ 5733 NSString *name = [applicationName copy]; 5734 [_private->applicationNameForUserAgent release]; 5735 _private->applicationNameForUserAgent = name; 5736 if (!_private->userAgentOverridden) 5737 _private->userAgent = String(); 5738} 5739 5740- (NSString *)applicationNameForUserAgent 5741{ 5742 return [[_private->applicationNameForUserAgent retain] autorelease]; 5743} 5744 5745- (void)setCustomUserAgent:(NSString *)userAgentString 5746{ 5747 _private->userAgent = userAgentString; 5748 _private->userAgentOverridden = userAgentString != nil; 5749} 5750 5751- (NSString *)customUserAgent 5752{ 5753 if (!_private->userAgentOverridden) 5754 return nil; 5755 return _private->userAgent; 5756} 5757 5758- (void)setMediaStyle:(NSString *)mediaStyle 5759{ 5760 if (_private->mediaStyle != mediaStyle) { 5761 [_private->mediaStyle release]; 5762 _private->mediaStyle = [mediaStyle copy]; 5763 } 5764} 5765 5766- (NSString *)mediaStyle 5767{ 5768 return _private->mediaStyle; 5769} 5770 5771- (BOOL)supportsTextEncoding 5772{ 5773 id documentView = [[[self mainFrame] frameView] documentView]; 5774 return [documentView conformsToProtocol:@protocol(WebDocumentText)] 5775 && [documentView supportsTextEncoding]; 5776} 5777 5778- (void)setCustomTextEncodingName:(NSString *)encoding 5779{ 5780 NSString *oldEncoding = [self customTextEncodingName]; 5781 if (encoding == oldEncoding || [encoding isEqualToString:oldEncoding]) 5782 return; 5783 if (Frame* mainFrame = [self _mainCoreFrame]) 5784 mainFrame->loader().reloadWithOverrideEncoding(encoding); 5785} 5786 5787- (NSString *)_mainFrameOverrideEncoding 5788{ 5789 WebDataSource *dataSource = [[self mainFrame] provisionalDataSource]; 5790 if (dataSource == nil) 5791 dataSource = [[self mainFrame] _dataSource]; 5792 if (dataSource == nil) 5793 return nil; 5794 return nsStringNilIfEmpty([dataSource _documentLoader]->overrideEncoding()); 5795} 5796 5797- (NSString *)customTextEncodingName 5798{ 5799 return [self _mainFrameOverrideEncoding]; 5800} 5801 5802- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script 5803{ 5804#if !PLATFORM(IOS) 5805 // Return statements are only valid in a function but some applications pass in scripts 5806 // prefixed with return (<rdar://problems/5103720&4616860>) since older WebKit versions 5807 // silently ignored the return. If the application is linked against an earlier version 5808 // of WebKit we will strip the return so the script wont fail. 5809 if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_JAVASCRIPT_RETURN_QUIRK)) { 5810 NSRange returnStringRange = [script rangeOfString:@"return "]; 5811 if (returnStringRange.length && !returnStringRange.location) 5812 script = [script substringFromIndex:returnStringRange.location + returnStringRange.length]; 5813 } 5814#endif 5815 5816 NSString *result = [[self mainFrame] _stringByEvaluatingJavaScriptFromString:script]; 5817 // The only way stringByEvaluatingJavaScriptFromString can return nil is if the frame was removed by the script 5818 // Since there's no way to get rid of the main frame, result will never ever be nil here. 5819 ASSERT(result); 5820 5821 return result; 5822} 5823 5824- (WebScriptObject *)windowScriptObject 5825{ 5826 Frame* coreFrame = [self _mainCoreFrame]; 5827 if (!coreFrame) 5828 return nil; 5829 return coreFrame->script().windowScriptObject(); 5830} 5831 5832- (String)_userAgentString 5833{ 5834 if (_private->userAgent.isNull()) 5835 _private->userAgent = [[self class] _standardUserAgentWithApplicationName:_private->applicationNameForUserAgent]; 5836 5837 return _private->userAgent; 5838} 5839 5840// Get the appropriate user-agent string for a particular URL. 5841- (NSString *)userAgentForURL:(NSURL *)url 5842{ 5843 return [self _userAgentString]; 5844} 5845 5846- (void)setHostWindow:(NSWindow *)hostWindow 5847{ 5848 if (_private->closed && hostWindow) 5849 return; 5850 if (hostWindow == _private->hostWindow) 5851 return; 5852 5853 Frame* coreFrame = [self _mainCoreFrame]; 5854#if !PLATFORM(IOS) 5855 for (Frame* frame = coreFrame; frame; frame = frame->tree().traverseNext(coreFrame)) 5856 [[[kit(frame) frameView] documentView] viewWillMoveToHostWindow:hostWindow]; 5857 if (_private->hostWindow && [self window] != _private->hostWindow) 5858 [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowWillCloseNotification object:_private->hostWindow]; 5859 if (hostWindow) 5860 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillClose:) name:NSWindowWillCloseNotification object:hostWindow]; 5861#endif 5862 [_private->hostWindow release]; 5863 _private->hostWindow = [hostWindow retain]; 5864 for (Frame* frame = coreFrame; frame; frame = frame->tree().traverseNext(coreFrame)) 5865 [[[kit(frame) frameView] documentView] viewDidMoveToHostWindow]; 5866#if !PLATFORM(IOS) 5867 _private->page->setDeviceScaleFactor([self _deviceScaleFactor]); 5868#endif 5869} 5870 5871- (NSWindow *)hostWindow 5872{ 5873 // -[WebView hostWindow] can sometimes be called from the WebView's [super dealloc] method 5874 // so we check here to make sure it's not null. 5875 if (!_private) 5876 return nil; 5877 5878 return _private->hostWindow; 5879} 5880 5881- (NSView <WebDocumentView> *)documentViewAtWindowPoint:(NSPoint)point 5882{ 5883 return [[self _frameViewAtWindowPoint:point] documentView]; 5884} 5885 5886- (NSDictionary *)_elementAtWindowPoint:(NSPoint)windowPoint 5887{ 5888 WebFrameView *frameView = [self _frameViewAtWindowPoint:windowPoint]; 5889 if (!frameView) 5890 return nil; 5891 NSView <WebDocumentView> *documentView = [frameView documentView]; 5892 if ([documentView conformsToProtocol:@protocol(WebDocumentElement)]) { 5893 NSPoint point = [documentView convertPoint:windowPoint fromView:nil]; 5894 return [(NSView <WebDocumentElement> *)documentView elementAtPoint:point]; 5895 } 5896 return [NSDictionary dictionaryWithObject:[frameView webFrame] forKey:WebElementFrameKey]; 5897} 5898 5899- (NSDictionary *)elementAtPoint:(NSPoint)point 5900{ 5901 return [self _elementAtWindowPoint:[self convertPoint:point toView:nil]]; 5902} 5903 5904#if ENABLE(DRAG_SUPPORT) 5905// The following 2 internal NSView methods are called on the drag destination to make scrolling while dragging work. 5906// Scrolling while dragging will only work if the drag destination is in a scroll view. The WebView is the drag destination. 5907// When dragging to a WebView, the document subview should scroll, but it doesn't because it is not the drag destination. 5908// Forward these calls to the document subview to make its scroll view scroll. 5909- (void)_autoscrollForDraggingInfo:(id)draggingInfo timeDelta:(NSTimeInterval)repeatDelta 5910{ 5911 NSView <WebDocumentView> *documentView = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]]; 5912 [documentView _autoscrollForDraggingInfo:draggingInfo timeDelta:repeatDelta]; 5913} 5914 5915- (BOOL)_shouldAutoscrollForDraggingInfo:(id)draggingInfo 5916{ 5917 NSView <WebDocumentView> *documentView = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]]; 5918 return [documentView _shouldAutoscrollForDraggingInfo:draggingInfo]; 5919} 5920 5921- (DragApplicationFlags)applicationFlags:(id <NSDraggingInfo>)draggingInfo 5922{ 5923 uint32_t flags = 0; 5924 if ([NSApp modalWindow]) 5925 flags = DragApplicationIsModal; 5926 if ([[self window] attachedSheet]) 5927 flags |= DragApplicationHasAttachedSheet; 5928 if ([draggingInfo draggingSource] == self) 5929 flags |= DragApplicationIsSource; 5930 if ([[NSApp currentEvent] modifierFlags] & NSAlternateKeyMask) 5931 flags |= DragApplicationIsCopyKeyDown; 5932 return static_cast<DragApplicationFlags>(flags); 5933} 5934 5935- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)draggingInfo 5936{ 5937 IntPoint client([draggingInfo draggingLocation]); 5938 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window])); 5939 DragData dragData(draggingInfo, client, global, static_cast<DragOperation>([draggingInfo draggingSourceOperationMask]), [self applicationFlags:draggingInfo]); 5940 return core(self)->dragController().dragEntered(dragData); 5941} 5942 5943- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)draggingInfo 5944{ 5945 Page* page = core(self); 5946 if (!page) 5947 return NSDragOperationNone; 5948 5949 IntPoint client([draggingInfo draggingLocation]); 5950 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window])); 5951 DragData dragData(draggingInfo, client, global, static_cast<DragOperation>([draggingInfo draggingSourceOperationMask]), [self applicationFlags:draggingInfo]); 5952 return page->dragController().dragUpdated(dragData); 5953} 5954 5955- (void)draggingExited:(id <NSDraggingInfo>)draggingInfo 5956{ 5957 Page* page = core(self); 5958 if (!page) 5959 return; 5960 5961 IntPoint client([draggingInfo draggingLocation]); 5962 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window])); 5963 DragData dragData(draggingInfo, client, global, static_cast<DragOperation>([draggingInfo draggingSourceOperationMask]), [self applicationFlags:draggingInfo]); 5964 page->dragController().dragExited(dragData); 5965} 5966 5967- (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)draggingInfo 5968{ 5969 return YES; 5970} 5971 5972- (BOOL)performDragOperation:(id <NSDraggingInfo>)draggingInfo 5973{ 5974 IntPoint client([draggingInfo draggingLocation]); 5975 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window])); 5976 DragData dragData(draggingInfo, client, global, static_cast<DragOperation>([draggingInfo draggingSourceOperationMask]), [self applicationFlags:draggingInfo]); 5977 return core(self)->dragController().performDragOperation(dragData); 5978} 5979 5980- (NSView *)_hitTest:(NSPoint *)point dragTypes:(NSSet *)types 5981{ 5982 NSView *hitView = [super _hitTest:point dragTypes:types]; 5983 if (!hitView && [[self superview] mouse:*point inRect:[self frame]]) 5984 return self; 5985 return hitView; 5986} 5987#endif 5988 5989- (BOOL)acceptsFirstResponder 5990{ 5991 return [[[self mainFrame] frameView] acceptsFirstResponder]; 5992} 5993 5994- (BOOL)becomeFirstResponder 5995{ 5996 if (_private->becomingFirstResponder) { 5997 // Fix for unrepro infinite recursion reported in Radar 4448181. If we hit this assert on 5998 // a debug build, we should figure out what causes the problem and do a better fix. 5999 ASSERT_NOT_REACHED(); 6000 return NO; 6001 } 6002 6003 // This works together with setNextKeyView to splice the WebView into 6004 // the key loop similar to the way NSScrollView does this. Note that 6005 // WebFrameView has very similar code. 6006#if !PLATFORM(IOS) 6007 NSWindow *window = [self window]; 6008#endif 6009 WebFrameView *mainFrameView = [[self mainFrame] frameView]; 6010 6011#if !PLATFORM(IOS) 6012 NSResponder *previousFirstResponder = [[self window] _oldFirstResponderBeforeBecoming]; 6013 BOOL fromOutside = ![previousFirstResponder isKindOfClass:[NSView class]] || (![(NSView *)previousFirstResponder isDescendantOf:self] && previousFirstResponder != self); 6014 6015 if ([window keyViewSelectionDirection] == NSSelectingPrevious) { 6016 NSView *previousValidKeyView = [self previousValidKeyView]; 6017 if (previousValidKeyView != self && previousValidKeyView != mainFrameView) { 6018 _private->becomingFirstResponder = YES; 6019 _private->becomingFirstResponderFromOutside = fromOutside; 6020 [window makeFirstResponder:previousValidKeyView]; 6021 _private->becomingFirstResponderFromOutside = NO; 6022 _private->becomingFirstResponder = NO; 6023 return YES; 6024 } 6025 return NO; 6026 } 6027#endif 6028 6029 if ([mainFrameView acceptsFirstResponder]) { 6030#if !PLATFORM(IOS) 6031 _private->becomingFirstResponder = YES; 6032 _private->becomingFirstResponderFromOutside = fromOutside; 6033 [window makeFirstResponder:mainFrameView]; 6034 _private->becomingFirstResponderFromOutside = NO; 6035 _private->becomingFirstResponder = NO; 6036#endif 6037 return YES; 6038 } 6039 6040 return NO; 6041} 6042 6043- (NSView *)_webcore_effectiveFirstResponder 6044{ 6045 if (WebFrameView *frameView = [[self mainFrame] frameView]) 6046 return [frameView _webcore_effectiveFirstResponder]; 6047 6048 return [super _webcore_effectiveFirstResponder]; 6049} 6050 6051- (void)setNextKeyView:(NSView *)view 6052{ 6053 // This works together with becomeFirstResponder to splice the WebView into 6054 // the key loop similar to the way NSScrollView does this. Note that 6055 // WebFrameView has similar code. 6056 if (WebFrameView *mainFrameView = [[self mainFrame] frameView]) { 6057 [mainFrameView setNextKeyView:view]; 6058 return; 6059 } 6060 6061 [super setNextKeyView:view]; 6062} 6063 6064static WebFrame *incrementFrame(WebFrame *frame, WebFindOptions options = 0) 6065{ 6066 Frame* coreFrame = core(frame); 6067 return kit((options & WebFindOptionsBackwards) 6068 ? coreFrame->tree().traversePreviousWithWrap(options & WebFindOptionsWrapAround) 6069 : coreFrame->tree().traverseNextWithWrap(options & WebFindOptionsWrapAround)); 6070} 6071 6072- (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag 6073{ 6074 return [self searchFor:string direction:forward caseSensitive:caseFlag wrap:wrapFlag startInSelection:NO]; 6075} 6076 6077+ (void)registerViewClass:(Class)viewClass representationClass:(Class)representationClass forMIMEType:(NSString *)MIMEType 6078{ 6079 [[WebFrameView _viewTypesAllowImageTypeOmission:YES] setObject:viewClass forKey:MIMEType]; 6080 [[WebDataSource _repTypesAllowImageTypeOmission:YES] setObject:representationClass forKey:MIMEType]; 6081 6082 // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed) 6083 // in the WebCore MIMEType registry. For now we're doing this in a safe, limited manner 6084 // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness 6085 if ([viewClass class] == [WebHTMLView class]) 6086 MIMETypeRegistry::getSupportedNonImageMIMETypes().add(MIMEType); 6087} 6088 6089- (void)setGroupName:(NSString *)groupName 6090{ 6091 if (_private->group) 6092 _private->group->removeWebView(self); 6093 6094 _private->group = WebViewGroup::getOrCreate(groupName); 6095 _private->group->addWebView(self); 6096 6097 if (!_private->page) 6098 return; 6099 _private->page->setGroupName(groupName); 6100} 6101 6102- (NSString *)groupName 6103{ 6104 if (!_private->page) 6105 return nil; 6106 return _private->page->groupName(); 6107} 6108 6109- (double)estimatedProgress 6110{ 6111 if (!_private->page) 6112 return 0.0; 6113 return _private->page->progress().estimatedProgress(); 6114} 6115 6116#if !PLATFORM(IOS) 6117- (NSArray *)pasteboardTypesForSelection 6118{ 6119 NSView <WebDocumentView> *documentView = [[[self _selectedOrMainFrame] frameView] documentView]; 6120 if ([documentView conformsToProtocol:@protocol(WebDocumentSelection)]) { 6121 return [(NSView <WebDocumentSelection> *)documentView pasteboardTypesForSelection]; 6122 } 6123 return [NSArray array]; 6124} 6125 6126- (void)writeSelectionWithPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard 6127{ 6128 WebFrame *frame = [self _selectedOrMainFrame]; 6129 if (frame && [frame _hasSelection]) { 6130 NSView <WebDocumentView> *documentView = [[frame frameView] documentView]; 6131 if ([documentView conformsToProtocol:@protocol(WebDocumentSelection)]) 6132 [(NSView <WebDocumentSelection> *)documentView writeSelectionWithPasteboardTypes:types toPasteboard:pasteboard]; 6133 } 6134} 6135 6136- (NSArray *)pasteboardTypesForElement:(NSDictionary *)element 6137{ 6138 if ([element objectForKey:WebElementImageURLKey] != nil) { 6139 return [NSPasteboard _web_writableTypesForImageIncludingArchive:([element objectForKey:WebElementDOMNodeKey] != nil)]; 6140 } else if ([element objectForKey:WebElementLinkURLKey] != nil) { 6141 return [NSPasteboard _web_writableTypesForURL]; 6142 } else if ([[element objectForKey:WebElementIsSelectedKey] boolValue]) { 6143 return [self pasteboardTypesForSelection]; 6144 } 6145 return [NSArray array]; 6146} 6147 6148- (void)writeElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard 6149{ 6150 if ([element objectForKey:WebElementImageURLKey] != nil) { 6151 [self _writeImageForElement:element withPasteboardTypes:types toPasteboard:pasteboard]; 6152 } else if ([element objectForKey:WebElementLinkURLKey] != nil) { 6153 [self _writeLinkElement:element withPasteboardTypes:types toPasteboard:pasteboard]; 6154 } else if ([[element objectForKey:WebElementIsSelectedKey] boolValue]) { 6155 [self writeSelectionWithPasteboardTypes:types toPasteboard:pasteboard]; 6156 } 6157} 6158 6159- (void)moveDragCaretToPoint:(NSPoint)point 6160{ 6161#if ENABLE(DRAG_SUPPORT) 6162 if (Page* page = core(self)) 6163 page->dragController().placeDragCaret(IntPoint([self convertPoint:point toView:nil])); 6164#endif 6165} 6166 6167- (void)removeDragCaret 6168{ 6169#if ENABLE(DRAG_SUPPORT) 6170 if (Page* page = core(self)) 6171 page->dragController().dragEnded(); 6172#endif 6173} 6174#endif // !PLATFORM(IOS) 6175 6176- (void)setMainFrameURL:(NSString *)URLString 6177{ 6178 NSURL *url; 6179 if ([URLString hasPrefix:@"/"]) 6180 url = [NSURL fileURLWithPath:URLString]; 6181 else 6182 url = [NSURL _web_URLWithDataAsString:URLString]; 6183 6184 [[self mainFrame] loadRequest:[NSURLRequest requestWithURL:url]]; 6185} 6186 6187- (NSString *)mainFrameURL 6188{ 6189 WebDataSource *ds; 6190 ds = [[self mainFrame] provisionalDataSource]; 6191 if (!ds) 6192 ds = [[self mainFrame] _dataSource]; 6193 return [[[ds request] URL] _web_originalDataAsString]; 6194} 6195 6196- (BOOL)isLoading 6197{ 6198 LOG (Bindings, "isLoading = %d", (int)[self _isLoading]); 6199 return [self _isLoading]; 6200} 6201 6202- (NSString *)mainFrameTitle 6203{ 6204 NSString *mainFrameTitle = [[[self mainFrame] _dataSource] pageTitle]; 6205 return (mainFrameTitle != nil) ? mainFrameTitle : (NSString *)@""; 6206} 6207 6208#if !PLATFORM(IOS) 6209- (NSImage *)mainFrameIcon 6210{ 6211 return [[WebIconDatabase sharedIconDatabase] iconForURL:[[[[self mainFrame] _dataSource] _URL] _web_originalDataAsString] withSize:WebIconSmallSize]; 6212} 6213#else 6214- (NSURL *)mainFrameIconURL 6215{ 6216 WebFrame *mainFrame = [self mainFrame]; 6217 Frame *coreMainFrame = core(mainFrame); 6218 if (!coreMainFrame) 6219 return nil; 6220 6221 NSURL *url = (NSURL *)coreMainFrame->loader().icon().url(); 6222 return url; 6223} 6224#endif 6225 6226- (DOMDocument *)mainFrameDocument 6227{ 6228 // only return the actual value if the state we're in gives NSTreeController 6229 // enough time to release its observers on the old model 6230 if (_private->mainFrameDocumentReady) 6231 return [[self mainFrame] DOMDocument]; 6232 return nil; 6233} 6234 6235- (void)setDrawsBackground:(BOOL)drawsBackground 6236{ 6237 if (_private->drawsBackground == drawsBackground) 6238 return; 6239 _private->drawsBackground = drawsBackground; 6240 [[self mainFrame] _updateBackgroundAndUpdatesWhileOffscreen]; 6241} 6242 6243- (BOOL)drawsBackground 6244{ 6245 // This method can be called beneath -[NSView dealloc] after we have cleared _private, 6246 // indirectly via -[WebFrameView viewDidMoveToWindow]. 6247 return !_private || _private->drawsBackground; 6248} 6249 6250- (void)setShouldUpdateWhileOffscreen:(BOOL)updateWhileOffscreen 6251{ 6252 if (_private->shouldUpdateWhileOffscreen == updateWhileOffscreen) 6253 return; 6254 _private->shouldUpdateWhileOffscreen = updateWhileOffscreen; 6255 [[self mainFrame] _updateBackgroundAndUpdatesWhileOffscreen]; 6256} 6257 6258- (BOOL)shouldUpdateWhileOffscreen 6259{ 6260 return _private->shouldUpdateWhileOffscreen; 6261} 6262 6263- (void)setCurrentNodeHighlight:(WebNodeHighlight *)nodeHighlight 6264{ 6265 id old = _private->currentNodeHighlight; 6266 _private->currentNodeHighlight = [nodeHighlight retain]; 6267 [old release]; 6268} 6269 6270- (WebNodeHighlight *)currentNodeHighlight 6271{ 6272 return _private->currentNodeHighlight; 6273} 6274 6275- (NSView *)previousValidKeyView 6276{ 6277 NSView *result = [super previousValidKeyView]; 6278 6279 // Work around AppKit bug 6905484. If the result is a view that's inside this one, it's 6280 // possible it is the wrong answer, because the fact that it's a descendant causes the 6281 // code that implements key view redirection to fail; this means we won't redirect to 6282 // the toolbar, for example, when we hit the edge of a window. Since the bug is specific 6283 // to cases where the receiver of previousValidKeyView is an ancestor of the last valid 6284 // key view in the loop, we can sidestep it by walking along previous key views until 6285 // we find one that is not a superview, then using that to call previousValidKeyView. 6286 6287 if (![result isDescendantOf:self]) 6288 return result; 6289 6290 // Use a visited set so we don't loop indefinitely when walking crazy key loops. 6291 // AppKit uses such sets internally and we want our loop to be as robust as its loops. 6292 RetainPtr<CFMutableSetRef> visitedViews = adoptCF(CFSetCreateMutable(0, 0, 0)); 6293 CFSetAddValue(visitedViews.get(), result); 6294 6295 NSView *previousView = self; 6296 do { 6297 CFSetAddValue(visitedViews.get(), previousView); 6298 previousView = [previousView previousKeyView]; 6299 if (!previousView || CFSetGetValue(visitedViews.get(), previousView)) 6300 return result; 6301 } while ([result isDescendantOf:previousView]); 6302 return [previousView previousValidKeyView]; 6303} 6304 6305@end 6306 6307@implementation WebView (WebIBActions) 6308 6309- (IBAction)takeStringURLFrom: sender 6310{ 6311 NSString *URLString = [sender stringValue]; 6312 6313 [[self mainFrame] loadRequest: [NSURLRequest requestWithURL: [NSURL _web_URLWithDataAsString: URLString]]]; 6314} 6315 6316- (BOOL)canGoBack 6317{ 6318#if PLATFORM(IOS) 6319 WebThreadLock(); 6320 if (!_private->page) 6321#else 6322 if (!_private->page || _private->page->defersLoading()) 6323#endif 6324 return NO; 6325 6326 return _private->page->backForward().canGoBackOrForward(-1); 6327} 6328 6329- (BOOL)canGoForward 6330{ 6331#if PLATFORM(IOS) 6332 WebThreadLock(); 6333 if (!_private->page) 6334#else 6335 if (!_private->page || _private->page->defersLoading()) 6336#endif 6337 return NO; 6338 6339 return !!_private->page->backForward().canGoBackOrForward(1); 6340} 6341 6342- (IBAction)goBack:(id)sender 6343{ 6344 [self goBack]; 6345} 6346 6347- (IBAction)goForward:(id)sender 6348{ 6349 [self goForward]; 6350} 6351 6352- (IBAction)stopLoading:(id)sender 6353{ 6354#if PLATFORM(IOS) 6355 if (WebThreadNotCurrent()) { 6356 _private->isStopping = true; 6357 WebThreadSetShouldYield(); 6358 } 6359 WebThreadRun(^{ 6360 _private->isStopping = false; 6361#endif 6362 [[self mainFrame] stopLoading]; 6363#if PLATFORM(IOS) 6364 }); 6365#endif 6366} 6367 6368#if PLATFORM(IOS) 6369- (void)stopLoadingAndClear 6370{ 6371 if (WebThreadNotCurrent() && !WebThreadIsLocked()) { 6372 _private->isStopping = true; 6373 WebThreadSetShouldYield(); 6374 } 6375 WebThreadRun(^{ 6376 _private->isStopping = false; 6377 6378 WebFrame *frame = [self mainFrame]; 6379 [frame stopLoading]; 6380 core(frame)->document()->loader()->writer().end(); // End to finish parsing and display immediately 6381 6382 WebFrameView *mainFrameView = [frame frameView]; 6383 float scale = [[mainFrameView documentView] scale]; 6384 WebPlainWhiteView *plainWhiteView = [[WebPlainWhiteView alloc] initWithFrame:NSZeroRect]; 6385 [plainWhiteView setScale:scale]; 6386 [plainWhiteView setFrame:[mainFrameView bounds]]; 6387 [mainFrameView _setDocumentView:plainWhiteView]; 6388 [plainWhiteView setNeedsDisplay:YES]; 6389 [plainWhiteView release]; 6390 }); 6391} 6392#endif 6393 6394- (IBAction)reload:(id)sender 6395{ 6396#if PLATFORM(IOS) 6397 WebThreadRun(^{ 6398#endif 6399 [[self mainFrame] reload]; 6400#if PLATFORM(IOS) 6401 }); 6402#endif 6403} 6404 6405- (IBAction)reloadFromOrigin:(id)sender 6406{ 6407 [[self mainFrame] reloadFromOrigin]; 6408} 6409 6410// FIXME: This code should move into WebCore so that it is not duplicated in each WebKit. 6411// (This includes canMakeTextSmaller/Larger, makeTextSmaller/Larger, and canMakeTextStandardSize/makeTextStandardSize) 6412- (BOOL)canMakeTextSmaller 6413{ 6414 return [self _canZoomOut:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]]; 6415} 6416 6417- (IBAction)makeTextSmaller:(id)sender 6418{ 6419 return [self _zoomOut:sender isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]]; 6420} 6421 6422- (BOOL)canMakeTextLarger 6423{ 6424 return [self _canZoomIn:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]]; 6425} 6426 6427- (IBAction)makeTextLarger:(id)sender 6428{ 6429 return [self _zoomIn:sender isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]]; 6430} 6431 6432- (BOOL)canMakeTextStandardSize 6433{ 6434 return [self _canResetZoom:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]]; 6435} 6436 6437- (IBAction)makeTextStandardSize:(id)sender 6438{ 6439 return [self _resetZoom:sender isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]]; 6440} 6441 6442#if !PLATFORM(IOS) 6443- (IBAction)toggleSmartInsertDelete:(id)sender 6444{ 6445 [self setSmartInsertDeleteEnabled:![self smartInsertDeleteEnabled]]; 6446} 6447 6448- (IBAction)toggleContinuousSpellChecking:(id)sender 6449{ 6450 [self setContinuousSpellCheckingEnabled:![self isContinuousSpellCheckingEnabled]]; 6451} 6452 6453- (BOOL)_responderValidateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item 6454{ 6455 id responder = [self _responderForResponderOperations]; 6456 if (responder != self && [responder respondsToSelector:[item action]]) { 6457 if ([responder respondsToSelector:@selector(validateUserInterfaceItemWithoutDelegate:)]) 6458 return [responder validateUserInterfaceItemWithoutDelegate:item]; 6459 if ([responder respondsToSelector:@selector(validateUserInterfaceItem:)]) 6460 return [responder validateUserInterfaceItem:item]; 6461 return YES; 6462 } 6463 return NO; 6464} 6465 6466#define VALIDATE(name) \ 6467 else if (action == @selector(name:)) { return [self _responderValidateUserInterfaceItem:item]; } 6468 6469- (BOOL)validateUserInterfaceItemWithoutDelegate:(id <NSValidatedUserInterfaceItem>)item 6470{ 6471 SEL action = [item action]; 6472 6473 if (action == @selector(goBack:)) { 6474 return [self canGoBack]; 6475 } else if (action == @selector(goForward:)) { 6476 return [self canGoForward]; 6477 } else if (action == @selector(makeTextLarger:)) { 6478 return [self canMakeTextLarger]; 6479 } else if (action == @selector(makeTextSmaller:)) { 6480 return [self canMakeTextSmaller]; 6481 } else if (action == @selector(makeTextStandardSize:)) { 6482 return [self canMakeTextStandardSize]; 6483 } else if (action == @selector(reload:)) { 6484 return [[self mainFrame] _dataSource] != nil; 6485 } else if (action == @selector(stopLoading:)) { 6486 return [self _isLoading]; 6487 } else if (action == @selector(toggleContinuousSpellChecking:)) { 6488 BOOL checkMark = NO; 6489 BOOL retVal = NO; 6490 if ([self _continuousCheckingAllowed]) { 6491 checkMark = [self isContinuousSpellCheckingEnabled]; 6492 retVal = YES; 6493 } 6494 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) { 6495 NSMenuItem *menuItem = (NSMenuItem *)item; 6496 [menuItem setState:checkMark ? NSOnState : NSOffState]; 6497 } 6498 return retVal; 6499 } else if (action == @selector(toggleSmartInsertDelete:)) { 6500 BOOL checkMark = [self smartInsertDeleteEnabled]; 6501 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) { 6502 NSMenuItem *menuItem = (NSMenuItem *)item; 6503 [menuItem setState:checkMark ? NSOnState : NSOffState]; 6504 } 6505 return YES; 6506 } else if (action == @selector(toggleGrammarChecking:)) { 6507 BOOL checkMark = [self isGrammarCheckingEnabled]; 6508 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) { 6509 NSMenuItem *menuItem = (NSMenuItem *)item; 6510 [menuItem setState:checkMark ? NSOnState : NSOffState]; 6511 } 6512 return YES; 6513 } else if (action == @selector(toggleAutomaticQuoteSubstitution:)) { 6514 BOOL checkMark = [self isAutomaticQuoteSubstitutionEnabled]; 6515 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) { 6516 NSMenuItem *menuItem = (NSMenuItem *)item; 6517 [menuItem setState:checkMark ? NSOnState : NSOffState]; 6518 } 6519 return YES; 6520 } else if (action == @selector(toggleAutomaticLinkDetection:)) { 6521 BOOL checkMark = [self isAutomaticLinkDetectionEnabled]; 6522 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) { 6523 NSMenuItem *menuItem = (NSMenuItem *)item; 6524 [menuItem setState:checkMark ? NSOnState : NSOffState]; 6525 } 6526 return YES; 6527 } else if (action == @selector(toggleAutomaticDashSubstitution:)) { 6528 BOOL checkMark = [self isAutomaticDashSubstitutionEnabled]; 6529 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) { 6530 NSMenuItem *menuItem = (NSMenuItem *)item; 6531 [menuItem setState:checkMark ? NSOnState : NSOffState]; 6532 } 6533 return YES; 6534 } else if (action == @selector(toggleAutomaticTextReplacement:)) { 6535 BOOL checkMark = [self isAutomaticTextReplacementEnabled]; 6536 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) { 6537 NSMenuItem *menuItem = (NSMenuItem *)item; 6538 [menuItem setState:checkMark ? NSOnState : NSOffState]; 6539 } 6540 return YES; 6541 } else if (action == @selector(toggleAutomaticSpellingCorrection:)) { 6542 BOOL checkMark = [self isAutomaticSpellingCorrectionEnabled]; 6543 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) { 6544 NSMenuItem *menuItem = (NSMenuItem *)item; 6545 [menuItem setState:checkMark ? NSOnState : NSOffState]; 6546 } 6547 return YES; 6548 } 6549 FOR_EACH_RESPONDER_SELECTOR(VALIDATE) 6550 6551 return YES; 6552} 6553 6554- (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item 6555{ 6556 BOOL result = [self validateUserInterfaceItemWithoutDelegate:item]; 6557 return CallUIDelegateReturningBoolean(result, self, @selector(webView:validateUserInterfaceItem:defaultValidation:), item, result); 6558} 6559#endif // !PLATFORM(IOS) 6560 6561@end 6562 6563@implementation WebView (WebPendingPublic) 6564 6565#if !PLATFORM(IOS) 6566- (void)scheduleInRunLoop:(NSRunLoop *)runLoop forMode:(NSString *)mode 6567{ 6568#if USE(CFNETWORK) 6569 CFRunLoopRef schedulePairRunLoop = [runLoop getCFRunLoop]; 6570#else 6571 NSRunLoop *schedulePairRunLoop = runLoop; 6572#endif 6573 if (runLoop && mode) 6574 core(self)->addSchedulePair(SchedulePair::create(schedulePairRunLoop, (CFStringRef)mode)); 6575} 6576 6577- (void)unscheduleFromRunLoop:(NSRunLoop *)runLoop forMode:(NSString *)mode 6578{ 6579#if USE(CFNETWORK) 6580 CFRunLoopRef schedulePairRunLoop = [runLoop getCFRunLoop]; 6581#else 6582 NSRunLoop *schedulePairRunLoop = runLoop; 6583#endif 6584 if (runLoop && mode) 6585 core(self)->removeSchedulePair(SchedulePair::create(schedulePairRunLoop, (CFStringRef)mode)); 6586} 6587#endif 6588 6589static BOOL findString(NSView <WebDocumentSearching> *searchView, NSString *string, WebFindOptions options) 6590{ 6591 if ([searchView conformsToProtocol:@protocol(WebDocumentOptionsSearching)]) 6592 return [(NSView <WebDocumentOptionsSearching> *)searchView _findString:string options:options]; 6593 if ([searchView conformsToProtocol:@protocol(WebDocumentIncrementalSearching)]) 6594 return [(NSView <WebDocumentIncrementalSearching> *)searchView searchFor:string direction:!(options & WebFindOptionsBackwards) caseSensitive:!(options & WebFindOptionsCaseInsensitive) wrap:!!(options & WebFindOptionsWrapAround) startInSelection:!!(options & WebFindOptionsStartInSelection)]; 6595 return [searchView searchFor:string direction:!(options & WebFindOptionsBackwards) caseSensitive:!(options & WebFindOptionsCaseInsensitive) wrap:!!(options & WebFindOptionsWrapAround)]; 6596} 6597 6598- (BOOL)findString:(NSString *)string options:(WebFindOptions)options 6599{ 6600 if (_private->closed) 6601 return NO; 6602 6603 // Get the frame holding the selection, or start with the main frame 6604 WebFrame *startFrame = [self _selectedOrMainFrame]; 6605 6606 // Search the first frame, then all the other frames, in order 6607 NSView <WebDocumentSearching> *startSearchView = nil; 6608 WebFrame *frame = startFrame; 6609 do { 6610 WebFrame *nextFrame = incrementFrame(frame, options); 6611 6612 BOOL onlyOneFrame = (frame == nextFrame); 6613 ASSERT(!onlyOneFrame || frame == startFrame); 6614 6615 id <WebDocumentView> view = [[frame frameView] documentView]; 6616 if ([view conformsToProtocol:@protocol(WebDocumentSearching)]) { 6617 NSView <WebDocumentSearching> *searchView = (NSView <WebDocumentSearching> *)view; 6618 6619 if (frame == startFrame) 6620 startSearchView = searchView; 6621 6622 // In some cases we have to search some content twice; see comment later in this method. 6623 // We can avoid ever doing this in the common one-frame case by passing the wrap option through 6624 // here, and then bailing out before we get to the code that would search again in the 6625 // same content. 6626 WebFindOptions optionsForThisPass = onlyOneFrame ? options : (options & ~WebFindOptionsWrapAround); 6627 6628 if (findString(searchView, string, optionsForThisPass)) { 6629 if (frame != startFrame) 6630 [startFrame _clearSelection]; 6631 [[self window] makeFirstResponder:searchView]; 6632 return YES; 6633 } 6634 6635 if (onlyOneFrame) 6636 return NO; 6637 } 6638 frame = nextFrame; 6639 } while (frame && frame != startFrame); 6640 6641 // If there are multiple frames and WebFindOptionsWrapAround is set and we've visited each one without finding a result, we still need to search in the 6642 // first-searched frame up to the selection. However, the API doesn't provide a way to search only up to a particular point. The only 6643 // way to make sure the entire frame is searched is to pass WebFindOptionsWrapAround. When there are no matches, this will search 6644 // some content that we already searched on the first pass. In the worst case, we could search the entire contents of this frame twice. 6645 // To fix this, we'd need to add a mechanism to specify a range in which to search. 6646 if ((options & WebFindOptionsWrapAround) && startSearchView) { 6647 if (findString(startSearchView, string, options)) { 6648 [[self window] makeFirstResponder:startSearchView]; 6649 return YES; 6650 } 6651 } 6652 return NO; 6653} 6654 6655- (DOMRange *)DOMRangeOfString:(NSString *)string relativeTo:(DOMRange *)previousRange options:(WebFindOptions)options 6656{ 6657 if (!_private->page) 6658 return nil; 6659 6660 return kit(_private->page->rangeOfString(string, core(previousRange), coreOptions(options)).get()); 6661} 6662 6663- (void)setMainFrameDocumentReady:(BOOL)mainFrameDocumentReady 6664{ 6665 // by setting this to NO, calls to mainFrameDocument are forced to return nil 6666 // setting this to YES lets it return the actual DOMDocument value 6667 // we use this to tell NSTreeController to reset its observers and clear its state 6668 if (_private->mainFrameDocumentReady == mainFrameDocumentReady) 6669 return; 6670#if !PLATFORM(IOS) 6671 [self _willChangeValueForKey:_WebMainFrameDocumentKey]; 6672 _private->mainFrameDocumentReady = mainFrameDocumentReady; 6673 [self _didChangeValueForKey:_WebMainFrameDocumentKey]; 6674 // this will cause observers to call mainFrameDocument where this flag will be checked 6675#endif 6676} 6677 6678- (void)setTabKeyCyclesThroughElements:(BOOL)cyclesElements 6679{ 6680 _private->tabKeyCyclesThroughElementsChanged = YES; 6681 if (_private->page) 6682 _private->page->setTabKeyCyclesThroughElements(cyclesElements); 6683} 6684 6685- (BOOL)tabKeyCyclesThroughElements 6686{ 6687 return _private->page && _private->page->tabKeyCyclesThroughElements(); 6688} 6689 6690- (void)setScriptDebugDelegate:(id)delegate 6691{ 6692 _private->scriptDebugDelegate = delegate; 6693 [self _cacheScriptDebugDelegateImplementations]; 6694 6695 if (delegate) 6696 [self _attachScriptDebuggerToAllFrames]; 6697 else 6698 [self _detachScriptDebuggerFromAllFrames]; 6699} 6700 6701- (id)scriptDebugDelegate 6702{ 6703 return _private->scriptDebugDelegate; 6704} 6705 6706- (void)setHistoryDelegate:(id)delegate 6707{ 6708 _private->historyDelegate = delegate; 6709 [self _cacheHistoryDelegateImplementations]; 6710} 6711 6712- (id)historyDelegate 6713{ 6714 return _private->historyDelegate; 6715} 6716 6717- (BOOL)shouldClose 6718{ 6719 Frame* coreFrame = [self _mainCoreFrame]; 6720 if (!coreFrame) 6721 return YES; 6722 return coreFrame->loader().shouldClose(); 6723} 6724 6725#if !PLATFORM(IOS) 6726static NSAppleEventDescriptor* aeDescFromJSValue(ExecState* exec, JSC::JSValue jsValue) 6727{ 6728 NSAppleEventDescriptor* aeDesc = 0; 6729 if (jsValue.isBoolean()) 6730 return [NSAppleEventDescriptor descriptorWithBoolean:jsValue.asBoolean()]; 6731 if (jsValue.isString()) 6732 return [NSAppleEventDescriptor descriptorWithString:jsValue.getString(exec)]; 6733 if (jsValue.isNumber()) { 6734 double value = jsValue.asNumber(); 6735 int intValue = value; 6736 if (value == intValue) 6737 return [NSAppleEventDescriptor descriptorWithDescriptorType:typeSInt32 bytes:&intValue length:sizeof(intValue)]; 6738 return [NSAppleEventDescriptor descriptorWithDescriptorType:typeIEEE64BitFloatingPoint bytes:&value length:sizeof(value)]; 6739 } 6740 if (jsValue.isObject()) { 6741 JSObject* object = jsValue.getObject(); 6742 if (object->inherits(DateInstance::info())) { 6743 DateInstance* date = static_cast<DateInstance*>(object); 6744 double ms = date->internalNumber(); 6745 if (!std::isnan(ms)) { 6746 CFAbsoluteTime utcSeconds = ms / 1000 - kCFAbsoluteTimeIntervalSince1970; 6747 LongDateTime ldt; 6748 if (noErr == UCConvertCFAbsoluteTimeToLongDateTime(utcSeconds, &ldt)) 6749 return [NSAppleEventDescriptor descriptorWithDescriptorType:typeLongDateTime bytes:&ldt length:sizeof(ldt)]; 6750 } 6751 } 6752 else if (object->inherits(JSArray::info())) { 6753 DEPRECATED_DEFINE_STATIC_LOCAL(HashSet<JSObject*>, visitedElems, ()); 6754 if (!visitedElems.contains(object)) { 6755 visitedElems.add(object); 6756 6757 JSArray* array = static_cast<JSArray*>(object); 6758 aeDesc = [NSAppleEventDescriptor listDescriptor]; 6759 unsigned numItems = array->length(); 6760 for (unsigned i = 0; i < numItems; ++i) 6761 [aeDesc insertDescriptor:aeDescFromJSValue(exec, array->get(exec, i)) atIndex:0]; 6762 6763 visitedElems.remove(object); 6764 return aeDesc; 6765 } 6766 } 6767 JSC::JSValue primitive = object->toPrimitive(exec); 6768 if (exec->hadException()) { 6769 exec->clearException(); 6770 return [NSAppleEventDescriptor nullDescriptor]; 6771 } 6772 return aeDescFromJSValue(exec, primitive); 6773 } 6774 if (jsValue.isUndefined()) 6775 return [NSAppleEventDescriptor descriptorWithTypeCode:cMissingValue]; 6776 ASSERT(jsValue.isNull()); 6777 return [NSAppleEventDescriptor nullDescriptor]; 6778} 6779 6780- (NSAppleEventDescriptor *)aeDescByEvaluatingJavaScriptFromString:(NSString *)script 6781{ 6782 Frame* coreFrame = [self _mainCoreFrame]; 6783 if (!coreFrame) 6784 return nil; 6785 if (!coreFrame->document()) 6786 return nil; 6787 JSC::JSValue result = coreFrame->script().executeScript(script, true).jsValue(); 6788 if (!result) // FIXME: pass errors 6789 return 0; 6790 JSLockHolder lock(coreFrame->script().globalObject(mainThreadNormalWorld())->globalExec()); 6791 return aeDescFromJSValue(coreFrame->script().globalObject(mainThreadNormalWorld())->globalExec(), result); 6792} 6793#endif 6794 6795- (BOOL)canMarkAllTextMatches 6796{ 6797 if (_private->closed) 6798 return NO; 6799 6800 WebFrame *frame = [self mainFrame]; 6801 do { 6802 id <WebDocumentView> view = [[frame frameView] documentView]; 6803 if (view && ![view conformsToProtocol:@protocol(WebMultipleTextMatches)]) 6804 return NO; 6805 6806 frame = incrementFrame(frame); 6807 } while (frame); 6808 6809 return YES; 6810} 6811 6812- (NSUInteger)countMatchesForText:(NSString *)string options:(WebFindOptions)options highlight:(BOOL)highlight limit:(NSUInteger)limit markMatches:(BOOL)markMatches 6813{ 6814 return [self countMatchesForText:string inDOMRange:nil options:options highlight:highlight limit:limit markMatches:markMatches]; 6815} 6816 6817- (NSUInteger)countMatchesForText:(NSString *)string inDOMRange:(DOMRange *)range options:(WebFindOptions)options highlight:(BOOL)highlight limit:(NSUInteger)limit markMatches:(BOOL)markMatches 6818{ 6819 if (_private->closed) 6820 return 0; 6821 6822 WebFrame *frame = [self mainFrame]; 6823 unsigned matchCount = 0; 6824 do { 6825 id <WebDocumentView> view = [[frame frameView] documentView]; 6826 if ([view conformsToProtocol:@protocol(WebMultipleTextMatches)]) { 6827 if (markMatches) 6828 [(NSView <WebMultipleTextMatches>*)view setMarkedTextMatchesAreHighlighted:highlight]; 6829 6830 ASSERT(limit == 0 || matchCount < limit); 6831 matchCount += [(NSView <WebMultipleTextMatches>*)view countMatchesForText:string inDOMRange:range options:options limit:(limit == 0 ? 0 : limit - matchCount) markMatches:markMatches]; 6832 6833 // Stop looking if we've reached the limit. A limit of 0 means no limit. 6834 if (limit > 0 && matchCount >= limit) 6835 break; 6836 } 6837 6838 frame = incrementFrame(frame); 6839 } while (frame); 6840 6841 return matchCount; 6842} 6843 6844- (void)unmarkAllTextMatches 6845{ 6846 if (_private->closed) 6847 return; 6848 6849 WebFrame *frame = [self mainFrame]; 6850 do { 6851 id <WebDocumentView> view = [[frame frameView] documentView]; 6852 if ([view conformsToProtocol:@protocol(WebMultipleTextMatches)]) 6853 [(NSView <WebMultipleTextMatches>*)view unmarkAllTextMatches]; 6854 6855 frame = incrementFrame(frame); 6856 } while (frame); 6857} 6858 6859- (NSArray *)rectsForTextMatches 6860{ 6861 if (_private->closed) 6862 return [NSArray array]; 6863 6864 NSMutableArray *result = [NSMutableArray array]; 6865 WebFrame *frame = [self mainFrame]; 6866 do { 6867 id <WebDocumentView> view = [[frame frameView] documentView]; 6868 if ([view conformsToProtocol:@protocol(WebMultipleTextMatches)]) { 6869 NSView <WebMultipleTextMatches> *documentView = (NSView <WebMultipleTextMatches> *)view; 6870 NSRect documentViewVisibleRect = [documentView visibleRect]; 6871 NSArray *originalRects = [documentView rectsForTextMatches]; 6872 unsigned rectCount = [originalRects count]; 6873 unsigned rectIndex; 6874 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 6875 for (rectIndex = 0; rectIndex < rectCount; ++rectIndex) { 6876 NSRect r = [[originalRects objectAtIndex:rectIndex] rectValue]; 6877 // Clip rect to document view's visible rect so rect is confined to subframe 6878 r = NSIntersectionRect(r, documentViewVisibleRect); 6879 if (NSIsEmptyRect(r)) 6880 continue; 6881 6882 // Convert rect to our coordinate system 6883 r = [documentView convertRect:r toView:self]; 6884 [result addObject:[NSValue valueWithRect:r]]; 6885 if (rectIndex % 10 == 0) { 6886 [pool drain]; 6887 pool = [[NSAutoreleasePool alloc] init]; 6888 } 6889 } 6890 [pool drain]; 6891 } 6892 6893 frame = incrementFrame(frame); 6894 } while (frame); 6895 6896 return result; 6897} 6898 6899- (void)scrollDOMRangeToVisible:(DOMRange *)range 6900{ 6901 [[[[range startContainer] ownerDocument] webFrame] _scrollDOMRangeToVisible:range]; 6902} 6903 6904#if PLATFORM(IOS) 6905- (void)scrollDOMRangeToVisible:(DOMRange *)range withInset:(CGFloat)inset 6906{ 6907 [[[[range startContainer] ownerDocument] webFrame] _scrollDOMRangeToVisible:range withInset:inset]; 6908} 6909#endif 6910 6911- (BOOL)allowsUndo 6912{ 6913 return _private->allowsUndo; 6914} 6915 6916- (void)setAllowsUndo:(BOOL)flag 6917{ 6918 _private->allowsUndo = flag; 6919} 6920 6921- (void)setPageSizeMultiplier:(float)m 6922{ 6923 [self _setZoomMultiplier:m isTextOnly:NO]; 6924} 6925 6926- (float)pageSizeMultiplier 6927{ 6928 return ![self _realZoomMultiplierIsTextOnly] ? _private->zoomMultiplier : 1.0f; 6929} 6930 6931- (BOOL)canZoomPageIn 6932{ 6933 return [self _canZoomIn:NO]; 6934} 6935 6936- (IBAction)zoomPageIn:(id)sender 6937{ 6938 return [self _zoomIn:sender isTextOnly:NO]; 6939} 6940 6941- (BOOL)canZoomPageOut 6942{ 6943 return [self _canZoomOut:NO]; 6944} 6945 6946- (IBAction)zoomPageOut:(id)sender 6947{ 6948 return [self _zoomOut:sender isTextOnly:NO]; 6949} 6950 6951- (BOOL)canResetPageZoom 6952{ 6953 return [self _canResetZoom:NO]; 6954} 6955 6956- (IBAction)resetPageZoom:(id)sender 6957{ 6958 return [self _resetZoom:sender isTextOnly:NO]; 6959} 6960 6961- (void)setMediaVolume:(float)volume 6962{ 6963 if (_private->page) 6964 _private->page->setMediaVolume(volume); 6965} 6966 6967- (float)mediaVolume 6968{ 6969 if (!_private->page) 6970 return 0; 6971 6972 return _private->page->mediaVolume(); 6973} 6974 6975- (void)addVisitedLinks:(NSArray *)visitedLinks 6976{ 6977 PageGroup& group = core(self)->group(); 6978 6979 NSEnumerator *enumerator = [visitedLinks objectEnumerator]; 6980 while (NSString *url = [enumerator nextObject]) { 6981 size_t length = [url length]; 6982 const UChar* characters = CFStringGetCharactersPtr(reinterpret_cast<CFStringRef>(url)); 6983 if (characters) 6984 group.addVisitedLink(characters, length); 6985 else { 6986 Vector<UChar, 512> buffer(length); 6987 [url getCharacters:buffer.data()]; 6988 group.addVisitedLink(buffer.data(), length); 6989 } 6990 } 6991} 6992 6993#if PLATFORM(IOS) 6994- (void)removeVisitedLink:(NSURL *)url 6995{ 6996 core(self)->group().removeVisitedLink(url); 6997} 6998#endif 6999 7000@end 7001 7002#if !PLATFORM(IOS) 7003@implementation WebView (WebViewPrintingPrivate) 7004 7005- (float)_headerHeight 7006{ 7007 return CallUIDelegateReturningFloat(self, @selector(webViewHeaderHeight:)); 7008} 7009 7010- (float)_footerHeight 7011{ 7012 return CallUIDelegateReturningFloat(self, @selector(webViewFooterHeight:)); 7013} 7014 7015- (void)_drawHeaderInRect:(NSRect)rect 7016{ 7017#ifdef DEBUG_HEADER_AND_FOOTER 7018 NSGraphicsContext *currentContext = [NSGraphicsContext currentContext]; 7019 [currentContext saveGraphicsState]; 7020 [[NSColor yellowColor] set]; 7021 NSRectFill(rect); 7022 [currentContext restoreGraphicsState]; 7023#endif 7024 7025 SEL selector = @selector(webView:drawHeaderInRect:); 7026 if (![_private->UIDelegate respondsToSelector:selector]) 7027 return; 7028 7029 NSGraphicsContext *currentContext = [NSGraphicsContext currentContext]; 7030 [currentContext saveGraphicsState]; 7031 7032 NSRectClip(rect); 7033 CallUIDelegate(self, selector, rect); 7034 7035 [currentContext restoreGraphicsState]; 7036} 7037 7038- (void)_drawFooterInRect:(NSRect)rect 7039{ 7040#ifdef DEBUG_HEADER_AND_FOOTER 7041 NSGraphicsContext *currentContext = [NSGraphicsContext currentContext]; 7042 [currentContext saveGraphicsState]; 7043 [[NSColor cyanColor] set]; 7044 NSRectFill(rect); 7045 [currentContext restoreGraphicsState]; 7046#endif 7047 7048 SEL selector = @selector(webView:drawFooterInRect:); 7049 if (![_private->UIDelegate respondsToSelector:selector]) 7050 return; 7051 7052 NSGraphicsContext *currentContext = [NSGraphicsContext currentContext]; 7053 [currentContext saveGraphicsState]; 7054 7055 NSRectClip(rect); 7056 CallUIDelegate(self, selector, rect); 7057 7058 [currentContext restoreGraphicsState]; 7059} 7060 7061- (void)_adjustPrintingMarginsForHeaderAndFooter 7062{ 7063 NSPrintOperation *op = [NSPrintOperation currentOperation]; 7064 NSPrintInfo *info = [op printInfo]; 7065 NSMutableDictionary *infoDictionary = [info dictionary]; 7066 7067 // We need to modify the top and bottom margins in the NSPrintInfo to account for the space needed by the 7068 // header and footer. Because this method can be called more than once on the same NSPrintInfo (see 5038087), 7069 // we stash away the unmodified top and bottom margins the first time this method is called, and we read from 7070 // those stashed-away values on subsequent calls. 7071 float originalTopMargin; 7072 float originalBottomMargin; 7073 NSNumber *originalTopMarginNumber = [infoDictionary objectForKey:WebKitOriginalTopPrintingMarginKey]; 7074 if (!originalTopMarginNumber) { 7075 ASSERT(![infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey]); 7076 originalTopMargin = [info topMargin]; 7077 originalBottomMargin = [info bottomMargin]; 7078 [infoDictionary setObject:[NSNumber numberWithFloat:originalTopMargin] forKey:WebKitOriginalTopPrintingMarginKey]; 7079 [infoDictionary setObject:[NSNumber numberWithFloat:originalBottomMargin] forKey:WebKitOriginalBottomPrintingMarginKey]; 7080 } else { 7081 ASSERT([originalTopMarginNumber isKindOfClass:[NSNumber class]]); 7082 ASSERT([[infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey] isKindOfClass:[NSNumber class]]); 7083 originalTopMargin = [originalTopMarginNumber floatValue]; 7084 originalBottomMargin = [[infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey] floatValue]; 7085 } 7086 7087 float scale = [op _web_pageSetupScaleFactor]; 7088 [info setTopMargin:originalTopMargin + [self _headerHeight] * scale]; 7089 [info setBottomMargin:originalBottomMargin + [self _footerHeight] * scale]; 7090} 7091 7092- (void)_drawHeaderAndFooter 7093{ 7094 // The header and footer rect height scales with the page, but the width is always 7095 // all the way across the printed page (inset by printing margins). 7096 NSPrintOperation *op = [NSPrintOperation currentOperation]; 7097 float scale = [op _web_pageSetupScaleFactor]; 7098 NSPrintInfo *printInfo = [op printInfo]; 7099 NSSize paperSize = [printInfo paperSize]; 7100 float headerFooterLeft = [printInfo leftMargin]/scale; 7101 float headerFooterWidth = (paperSize.width - ([printInfo leftMargin] + [printInfo rightMargin]))/scale; 7102 NSRect footerRect = NSMakeRect(headerFooterLeft, [printInfo bottomMargin]/scale - [self _footerHeight] , 7103 headerFooterWidth, [self _footerHeight]); 7104 NSRect headerRect = NSMakeRect(headerFooterLeft, (paperSize.height - [printInfo topMargin])/scale, 7105 headerFooterWidth, [self _headerHeight]); 7106 7107 [self _drawHeaderInRect:headerRect]; 7108 [self _drawFooterInRect:footerRect]; 7109} 7110@end 7111 7112@implementation WebView (WebDebugBinding) 7113 7114- (void)addObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context 7115{ 7116 LOG (Bindings, "addObserver:%p forKeyPath:%@ options:%x context:%p", anObserver, keyPath, options, context); 7117 [super addObserver:anObserver forKeyPath:keyPath options:options context:context]; 7118} 7119 7120- (void)removeObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath 7121{ 7122 LOG (Bindings, "removeObserver:%p forKeyPath:%@", anObserver, keyPath); 7123 [super removeObserver:anObserver forKeyPath:keyPath]; 7124} 7125 7126@end 7127 7128#endif // !PLATFORM(IOS) 7129 7130//========================================================================================== 7131// Editing 7132 7133@implementation WebView (WebViewCSS) 7134 7135- (DOMCSSStyleDeclaration *)computedStyleForElement:(DOMElement *)element pseudoElement:(NSString *)pseudoElement 7136{ 7137 // FIXME: is this the best level for this conversion? 7138 if (pseudoElement == nil) 7139 pseudoElement = @""; 7140 7141 return [[element ownerDocument] getComputedStyle:element pseudoElement:pseudoElement]; 7142} 7143 7144@end 7145 7146@implementation WebView (WebViewEditing) 7147 7148- (DOMRange *)editableDOMRangeForPoint:(NSPoint)point 7149{ 7150 Page* page = core(self); 7151 if (!page) 7152 return nil; 7153 return kit(page->mainFrame().editor().rangeForPoint(IntPoint([self convertPoint:point toView:nil])).get()); 7154} 7155 7156- (BOOL)_shouldChangeSelectedDOMRange:(DOMRange *)currentRange toDOMRange:(DOMRange *)proposedRange affinity:(NSSelectionAffinity)selectionAffinity stillSelecting:(BOOL)flag 7157{ 7158#if !PLATFORM(IOS) 7159 // FIXME: This quirk is needed due to <rdar://problem/4985321> - We can phase it out once Aperture can adopt the new behavior on their end 7160 if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_APERTURE_QUIRK) && [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.Aperture"]) 7161 return YES; 7162#endif 7163 return [[self _editingDelegateForwarder] webView:self shouldChangeSelectedDOMRange:currentRange toDOMRange:proposedRange affinity:selectionAffinity stillSelecting:flag]; 7164} 7165 7166- (BOOL)maintainsInactiveSelection 7167{ 7168 return NO; 7169} 7170 7171- (void)setSelectedDOMRange:(DOMRange *)range affinity:(NSSelectionAffinity)selectionAffinity 7172{ 7173 Frame* coreFrame = core([self _selectedOrMainFrame]); 7174 if (!coreFrame) 7175 return; 7176 7177 if (range == nil) 7178 coreFrame->selection().clear(); 7179 else { 7180 // Derive the frame to use from the range passed in. 7181 // Using _selectedOrMainFrame could give us a different document than 7182 // the one the range uses. 7183 coreFrame = core([range startContainer])->document().frame(); 7184 if (!coreFrame) 7185 return; 7186 7187 coreFrame->selection().setSelectedRange(core(range), core(selectionAffinity), true); 7188 } 7189} 7190 7191- (DOMRange *)selectedDOMRange 7192{ 7193 Frame* coreFrame = core([self _selectedOrMainFrame]); 7194 if (!coreFrame) 7195 return nil; 7196 return kit(coreFrame->selection().toNormalizedRange().get()); 7197} 7198 7199- (NSSelectionAffinity)selectionAffinity 7200{ 7201 Frame* coreFrame = core([self _selectedOrMainFrame]); 7202 if (!coreFrame) 7203 return NSSelectionAffinityDownstream; 7204 return kit(coreFrame->selection().selection().affinity()); 7205} 7206 7207- (void)setEditable:(BOOL)flag 7208{ 7209 if ([self isEditable] != flag && _private->page) { 7210 _private->page->setEditable(flag); 7211 if (!_private->tabKeyCyclesThroughElementsChanged) 7212 _private->page->setTabKeyCyclesThroughElements(!flag); 7213 Frame* mainFrame = [self _mainCoreFrame]; 7214 if (mainFrame) { 7215 if (flag) { 7216 mainFrame->editor().applyEditingStyleToBodyElement(); 7217 // If the WebView is made editable and the selection is empty, set it to something. 7218 if (![self selectedDOMRange]) 7219 mainFrame->selection().setSelectionFromNone(); 7220 } 7221 } 7222 } 7223} 7224 7225- (BOOL)isEditable 7226{ 7227 return _private->page && _private->page->isEditable(); 7228} 7229 7230- (void)setTypingStyle:(DOMCSSStyleDeclaration *)style 7231{ 7232 // We don't know enough at thls level to pass in a relevant WebUndoAction; we'd have to 7233 // change the API to allow this. 7234 [[self _selectedOrMainFrame] _setTypingStyle:style withUndoAction:EditActionUnspecified]; 7235} 7236 7237- (DOMCSSStyleDeclaration *)typingStyle 7238{ 7239 return [[self _selectedOrMainFrame] _typingStyle]; 7240} 7241 7242- (void)setSmartInsertDeleteEnabled:(BOOL)flag 7243{ 7244 if (_private->page->settings().smartInsertDeleteEnabled() != flag) { 7245 _private->page->settings().setSmartInsertDeleteEnabled(flag); 7246 [[NSUserDefaults standardUserDefaults] setBool:_private->page->settings().smartInsertDeleteEnabled() forKey:WebSmartInsertDeleteEnabled]; 7247 [self setSelectTrailingWhitespaceEnabled:!flag]; 7248 } 7249} 7250 7251- (BOOL)smartInsertDeleteEnabled 7252{ 7253 return _private->page->settings().smartInsertDeleteEnabled(); 7254} 7255 7256- (void)setContinuousSpellCheckingEnabled:(BOOL)flag 7257{ 7258 if (continuousSpellCheckingEnabled == flag) 7259 return; 7260 7261 continuousSpellCheckingEnabled = flag; 7262#if !PLATFORM(IOS) 7263 [[NSUserDefaults standardUserDefaults] setBool:continuousSpellCheckingEnabled forKey:WebContinuousSpellCheckingEnabled]; 7264#endif 7265 if ([self isContinuousSpellCheckingEnabled]) 7266 [[self class] _preflightSpellChecker]; 7267 else 7268 [[self mainFrame] _unmarkAllMisspellings]; 7269} 7270 7271- (BOOL)isContinuousSpellCheckingEnabled 7272{ 7273 return (continuousSpellCheckingEnabled && [self _continuousCheckingAllowed]); 7274} 7275 7276#if !PLATFORM(IOS) 7277- (NSInteger)spellCheckerDocumentTag 7278{ 7279 if (!_private->hasSpellCheckerDocumentTag) { 7280 _private->spellCheckerDocumentTag = [NSSpellChecker uniqueSpellDocumentTag]; 7281 _private->hasSpellCheckerDocumentTag = YES; 7282 } 7283 return _private->spellCheckerDocumentTag; 7284} 7285#endif 7286 7287- (NSUndoManager *)undoManager 7288{ 7289 if (!_private->allowsUndo) 7290 return nil; 7291 7292#if !PLATFORM(IOS) 7293 NSUndoManager *undoManager = [[self _editingDelegateForwarder] undoManagerForWebView:self]; 7294 if (undoManager) 7295 return undoManager; 7296 7297 return [super undoManager]; 7298#else 7299 return [[self _editingDelegateForwarder] undoManagerForWebView:self]; 7300#endif 7301} 7302 7303- (void)registerForEditingDelegateNotification:(NSString *)name selector:(SEL)selector 7304{ 7305 NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter]; 7306 if ([_private->editingDelegate respondsToSelector:selector]) 7307 [defaultCenter addObserver:_private->editingDelegate selector:selector name:name object:self]; 7308} 7309 7310- (void)setEditingDelegate:(id)delegate 7311{ 7312 if (_private->editingDelegate == delegate) 7313 return; 7314 7315 NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter]; 7316 7317 // remove notifications from current delegate 7318 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidBeginEditingNotification object:self]; 7319 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidChangeNotification object:self]; 7320 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidEndEditingNotification object:self]; 7321 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidChangeTypingStyleNotification object:self]; 7322 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidChangeSelectionNotification object:self]; 7323 7324 _private->editingDelegate = delegate; 7325 [_private->editingDelegateForwarder release]; 7326 _private->editingDelegateForwarder = nil; 7327 7328 // add notifications for new delegate 7329 [self registerForEditingDelegateNotification:WebViewDidBeginEditingNotification selector:@selector(webViewDidBeginEditing:)]; 7330 [self registerForEditingDelegateNotification:WebViewDidChangeNotification selector:@selector(webViewDidChange:)]; 7331 [self registerForEditingDelegateNotification:WebViewDidEndEditingNotification selector:@selector(webViewDidEndEditing:)]; 7332 [self registerForEditingDelegateNotification:WebViewDidChangeTypingStyleNotification selector:@selector(webViewDidChangeTypingStyle:)]; 7333 [self registerForEditingDelegateNotification:WebViewDidChangeSelectionNotification selector:@selector(webViewDidChangeSelection:)]; 7334} 7335 7336- (id)editingDelegate 7337{ 7338 return _private->editingDelegate; 7339} 7340 7341- (DOMCSSStyleDeclaration *)styleDeclarationWithText:(NSString *)text 7342{ 7343 // FIXME: Should this really be attached to the document with the current selection? 7344 DOMCSSStyleDeclaration *decl = [[[self _selectedOrMainFrame] DOMDocument] createCSSStyleDeclaration]; 7345 [decl setCssText:text]; 7346 return decl; 7347} 7348 7349@end 7350 7351#if !PLATFORM(IOS) 7352@implementation WebView (WebViewGrammarChecking) 7353 7354// FIXME: This method should be merged into WebViewEditing when we're not in API freeze 7355- (BOOL)isGrammarCheckingEnabled 7356{ 7357 return grammarCheckingEnabled; 7358} 7359 7360// FIXME: This method should be merged into WebViewEditing when we're not in API freeze 7361- (void)setGrammarCheckingEnabled:(BOOL)flag 7362{ 7363 if (grammarCheckingEnabled == flag) 7364 return; 7365 7366 grammarCheckingEnabled = flag; 7367 [[NSUserDefaults standardUserDefaults] setBool:grammarCheckingEnabled forKey:WebGrammarCheckingEnabled]; 7368 [[NSSpellChecker sharedSpellChecker] updatePanels]; 7369 7370 // We call _preflightSpellChecker when turning continuous spell checking on, but we don't need to do that here 7371 // because grammar checking only occurs on code paths that already preflight spell checking appropriately. 7372 7373 if (![self isGrammarCheckingEnabled]) 7374 [[self mainFrame] _unmarkAllBadGrammar]; 7375} 7376 7377// FIXME: This method should be merged into WebIBActions when we're not in API freeze 7378- (void)toggleGrammarChecking:(id)sender 7379{ 7380 [self setGrammarCheckingEnabled:![self isGrammarCheckingEnabled]]; 7381} 7382 7383@end 7384#endif 7385 7386@implementation WebView (WebViewTextChecking) 7387 7388- (BOOL)isAutomaticQuoteSubstitutionEnabled 7389{ 7390#if PLATFORM(IOS) 7391 return NO; 7392#else 7393 return automaticQuoteSubstitutionEnabled; 7394#endif 7395} 7396 7397- (BOOL)isAutomaticLinkDetectionEnabled 7398{ 7399#if PLATFORM(IOS) 7400 return NO; 7401#else 7402 return automaticLinkDetectionEnabled; 7403#endif 7404} 7405 7406- (BOOL)isAutomaticDashSubstitutionEnabled 7407{ 7408#if PLATFORM(IOS) 7409 return NO; 7410#else 7411 return automaticDashSubstitutionEnabled; 7412#endif 7413} 7414 7415- (BOOL)isAutomaticTextReplacementEnabled 7416{ 7417#if PLATFORM(IOS) 7418 return NO; 7419#else 7420 return automaticTextReplacementEnabled; 7421#endif 7422} 7423 7424- (BOOL)isAutomaticSpellingCorrectionEnabled 7425{ 7426#if PLATFORM(IOS) 7427 return NO; 7428#else 7429 return automaticSpellingCorrectionEnabled; 7430#endif 7431} 7432 7433#if !PLATFORM(IOS) 7434 7435- (void)setAutomaticQuoteSubstitutionEnabled:(BOOL)flag 7436{ 7437 if (automaticQuoteSubstitutionEnabled == flag) 7438 return; 7439 automaticQuoteSubstitutionEnabled = flag; 7440 [[NSUserDefaults standardUserDefaults] setBool:automaticQuoteSubstitutionEnabled forKey:WebAutomaticQuoteSubstitutionEnabled]; 7441 [[NSSpellChecker sharedSpellChecker] updatePanels]; 7442} 7443 7444- (void)toggleAutomaticQuoteSubstitution:(id)sender 7445{ 7446 [self setAutomaticQuoteSubstitutionEnabled:![self isAutomaticQuoteSubstitutionEnabled]]; 7447} 7448 7449- (void)setAutomaticLinkDetectionEnabled:(BOOL)flag 7450{ 7451 if (automaticLinkDetectionEnabled == flag) 7452 return; 7453 automaticLinkDetectionEnabled = flag; 7454 [[NSUserDefaults standardUserDefaults] setBool:automaticLinkDetectionEnabled forKey:WebAutomaticLinkDetectionEnabled]; 7455 [[NSSpellChecker sharedSpellChecker] updatePanels]; 7456} 7457 7458- (void)toggleAutomaticLinkDetection:(id)sender 7459{ 7460 [self setAutomaticLinkDetectionEnabled:![self isAutomaticLinkDetectionEnabled]]; 7461} 7462 7463- (void)setAutomaticDashSubstitutionEnabled:(BOOL)flag 7464{ 7465 if (automaticDashSubstitutionEnabled == flag) 7466 return; 7467 automaticDashSubstitutionEnabled = flag; 7468 [[NSUserDefaults standardUserDefaults] setBool:automaticDashSubstitutionEnabled forKey:WebAutomaticDashSubstitutionEnabled]; 7469 [[NSSpellChecker sharedSpellChecker] updatePanels]; 7470} 7471 7472- (void)toggleAutomaticDashSubstitution:(id)sender 7473{ 7474 [self setAutomaticDashSubstitutionEnabled:![self isAutomaticDashSubstitutionEnabled]]; 7475} 7476 7477- (void)setAutomaticTextReplacementEnabled:(BOOL)flag 7478{ 7479 if (automaticTextReplacementEnabled == flag) 7480 return; 7481 automaticTextReplacementEnabled = flag; 7482 [[NSUserDefaults standardUserDefaults] setBool:automaticTextReplacementEnabled forKey:WebAutomaticTextReplacementEnabled]; 7483 [[NSSpellChecker sharedSpellChecker] updatePanels]; 7484} 7485 7486- (void)toggleAutomaticTextReplacement:(id)sender 7487{ 7488 [self setAutomaticTextReplacementEnabled:![self isAutomaticTextReplacementEnabled]]; 7489} 7490 7491- (void)setAutomaticSpellingCorrectionEnabled:(BOOL)flag 7492{ 7493 if (automaticSpellingCorrectionEnabled == flag) 7494 return; 7495 automaticSpellingCorrectionEnabled = flag; 7496 [[NSUserDefaults standardUserDefaults] setBool:automaticSpellingCorrectionEnabled forKey:WebAutomaticSpellingCorrectionEnabled]; 7497 [[NSSpellChecker sharedSpellChecker] updatePanels]; 7498} 7499 7500- (void)toggleAutomaticSpellingCorrection:(id)sender 7501{ 7502 [self setAutomaticSpellingCorrectionEnabled:![self isAutomaticSpellingCorrectionEnabled]]; 7503} 7504 7505#endif // !PLATFORM(IOS) 7506 7507@end 7508 7509@implementation WebView (WebViewUndoableEditing) 7510 7511- (void)replaceSelectionWithNode:(DOMNode *)node 7512{ 7513 [[self _selectedOrMainFrame] _replaceSelectionWithNode:node selectReplacement:YES smartReplace:NO matchStyle:NO]; 7514} 7515 7516- (void)replaceSelectionWithText:(NSString *)text 7517{ 7518 [[self _selectedOrMainFrame] _replaceSelectionWithText:text selectReplacement:YES smartReplace:NO]; 7519} 7520 7521- (void)replaceSelectionWithMarkupString:(NSString *)markupString 7522{ 7523 [[self _selectedOrMainFrame] _replaceSelectionWithMarkupString:markupString baseURLString:nil selectReplacement:YES smartReplace:NO]; 7524} 7525 7526- (void)replaceSelectionWithArchive:(WebArchive *)archive 7527{ 7528 [[[self _selectedOrMainFrame] _dataSource] _replaceSelectionWithArchive:archive selectReplacement:YES]; 7529} 7530 7531- (void)deleteSelection 7532{ 7533 WebFrame *webFrame = [self _selectedOrMainFrame]; 7534 Frame* coreFrame = core(webFrame); 7535 if (coreFrame) 7536 coreFrame->editor().deleteSelectionWithSmartDelete([(WebHTMLView *)[[webFrame frameView] documentView] _canSmartCopyOrDelete]); 7537} 7538 7539- (void)applyStyle:(DOMCSSStyleDeclaration *)style 7540{ 7541 // We don't know enough at thls level to pass in a relevant WebUndoAction; we'd have to 7542 // change the API to allow this. 7543 WebFrame *webFrame = [self _selectedOrMainFrame]; 7544 if (Frame* coreFrame = core(webFrame)) { 7545 // FIXME: We shouldn't have to make a copy here. 7546 Ref<MutableStyleProperties> properties(core(style)->copyProperties()); 7547 coreFrame->editor().applyStyle(&properties.get()); 7548 } 7549} 7550 7551@end 7552 7553@implementation WebView (WebViewEditingActions) 7554 7555- (void)_performResponderOperation:(SEL)selector with:(id)parameter 7556{ 7557 static BOOL reentered = NO; 7558 if (reentered) { 7559 [[self nextResponder] tryToPerform:selector with:parameter]; 7560 return; 7561 } 7562 7563 // There are two possibilities here. 7564 // 7565 // One is that WebView has been called in its role as part of the responder chain. 7566 // In that case, it's fine to call the first responder and end up calling down the 7567 // responder chain again. Later we will return here with reentered = YES and continue 7568 // past the WebView. 7569 // 7570 // The other is that we are being called directly, in which case we want to pass the 7571 // selector down to the view inside us that can handle it, and continue down the 7572 // responder chain as usual. 7573 7574 // Pass this selector down to the first responder. 7575 NSResponder *responder = [self _responderForResponderOperations]; 7576 reentered = YES; 7577 [responder tryToPerform:selector with:parameter]; 7578 reentered = NO; 7579} 7580 7581#define FORWARD(name) \ 7582 - (void)name:(id)sender { [self _performResponderOperation:_cmd with:sender]; } 7583 7584FOR_EACH_RESPONDER_SELECTOR(FORWARD) 7585 7586#if PLATFORM(IOS) 7587FORWARD(clearText) 7588FORWARD(toggleBold) 7589FORWARD(toggleItalic) 7590FORWARD(toggleUnderline) 7591 7592- (void)insertDictationPhrases:(NSArray *)dictationPhrases metadata:(id)metadata 7593{ 7594 Frame* coreFrame = core([self _selectedOrMainFrame]); 7595 if (!coreFrame) 7596 return; 7597 7598 coreFrame->editor().insertDictationPhrases(vectorForDictationPhrasesArray(dictationPhrases), metadata); 7599} 7600#endif 7601 7602- (void)insertText:(NSString *)text 7603{ 7604 [self _performResponderOperation:_cmd with:text]; 7605} 7606 7607- (NSDictionary *)typingAttributes 7608{ 7609 Frame* coreFrame = core([self _selectedOrMainFrame]); 7610 if (coreFrame) 7611 return coreFrame->editor().fontAttributesForSelectionStart(); 7612 7613 return nil; 7614} 7615 7616 7617@end 7618 7619@implementation WebView (WebViewEditingInMail) 7620 7621- (void)_insertNewlineInQuotedContent 7622{ 7623 [[self _selectedOrMainFrame] _insertParagraphSeparatorInQuotedContent]; 7624} 7625 7626- (void)_replaceSelectionWithNode:(DOMNode *)node matchStyle:(BOOL)matchStyle 7627{ 7628 [[self _selectedOrMainFrame] _replaceSelectionWithNode:node selectReplacement:YES smartReplace:NO matchStyle:matchStyle]; 7629} 7630 7631- (BOOL)_selectionIsCaret 7632{ 7633 Frame* coreFrame = core([self _selectedOrMainFrame]); 7634 if (!coreFrame) 7635 return NO; 7636 return coreFrame->selection().isCaret(); 7637} 7638 7639- (BOOL)_selectionIsAll 7640{ 7641 Frame* coreFrame = core([self _selectedOrMainFrame]); 7642 if (!coreFrame) 7643 return NO; 7644 return coreFrame->selection().isAll(CanCrossEditingBoundary); 7645} 7646 7647- (void)_simplifyMarkup:(DOMNode *)startNode endNode:(DOMNode *)endNode 7648{ 7649 Frame* coreFrame = core([self mainFrame]); 7650 if (!coreFrame || !startNode) 7651 return; 7652 Node* coreStartNode= core(startNode); 7653 if (&coreStartNode->document() != coreFrame->document()) 7654 return; 7655 return coreFrame->editor().simplifyMarkup(coreStartNode, core(endNode)); 7656} 7657 7658@end 7659 7660static WebFrameView *containingFrameView(NSView *view) 7661{ 7662 while (view && ![view isKindOfClass:[WebFrameView class]]) 7663 view = [view superview]; 7664 return (WebFrameView *)view; 7665} 7666 7667@implementation WebView (WebFileInternal) 7668 7669#if !PLATFORM(IOS) 7670- (float)_deviceScaleFactor 7671{ 7672 if (_private->customDeviceScaleFactor != 0) 7673 return _private->customDeviceScaleFactor; 7674 7675 NSWindow *window = [self window]; 7676 NSWindow *hostWindow = [self hostWindow]; 7677 if (window) 7678 return [window backingScaleFactor]; 7679 if (hostWindow) 7680 return [hostWindow backingScaleFactor]; 7681 return [[NSScreen mainScreen] backingScaleFactor]; 7682} 7683#endif 7684 7685static inline uint64_t roundUpToPowerOf2(uint64_t num) 7686{ 7687 return powf(2.0, ceilf(log2f(num))); 7688} 7689 7690+ (void)_setCacheModel:(WebCacheModel)cacheModel 7691{ 7692 if (s_didSetCacheModel && cacheModel == s_cacheModel) 7693 return; 7694 7695 NSString *nsurlCacheDirectory = CFBridgingRelease(WKCopyFoundationCacheDirectory()); 7696 if (!nsurlCacheDirectory) 7697 nsurlCacheDirectory = NSHomeDirectory(); 7698 7699 static uint64_t memSize = roundUpToPowerOf2(WebMemorySize() / 1024 / 1024); 7700 unsigned long long diskFreeSize = WebVolumeFreeSize(nsurlCacheDirectory) / 1024 / 1000; 7701 NSURLCache *nsurlCache = [NSURLCache sharedURLCache]; 7702 7703 unsigned cacheTotalCapacity = 0; 7704 unsigned cacheMinDeadCapacity = 0; 7705 unsigned cacheMaxDeadCapacity = 0; 7706 auto deadDecodedDataDeletionInterval = std::chrono::seconds { 0 }; 7707 7708 unsigned pageCacheCapacity = 0; 7709 7710 NSUInteger nsurlCacheMemoryCapacity = 0; 7711 NSUInteger nsurlCacheDiskCapacity = 0; 7712#if PLATFORM(IOS) 7713 unsigned tileLayerPoolCapacity = 0; 7714#endif 7715 7716 switch (cacheModel) { 7717 case WebCacheModelDocumentViewer: { 7718 // Page cache capacity (in pages) 7719 pageCacheCapacity = 0; 7720 7721 // Object cache capacities (in bytes) 7722 if (memSize >= 4096) 7723 cacheTotalCapacity = 128 * 1024 * 1024; 7724 else if (memSize >= 2048) 7725 cacheTotalCapacity = 96 * 1024 * 1024; 7726 else if (memSize >= 1024) 7727 cacheTotalCapacity = 32 * 1024 * 1024; 7728 else if (memSize >= 512) 7729 cacheTotalCapacity = 16 * 1024 * 1024; 7730#if PLATFORM(IOS) 7731 else 7732 cacheTotalCapacity = 4 * 1024 * 1024; 7733#endif 7734 7735 cacheMinDeadCapacity = 0; 7736 cacheMaxDeadCapacity = 0; 7737 7738 // Foundation memory cache capacity (in bytes) 7739 nsurlCacheMemoryCapacity = 0; 7740 7741 // Foundation disk cache capacity (in bytes) 7742 nsurlCacheDiskCapacity = [nsurlCache diskCapacity]; 7743 7744#if PLATFORM(IOS) 7745 // TileCache layer pool capacity, in bytes. 7746 if (memSize >= 1024) 7747 tileLayerPoolCapacity = 24 * 1024 * 1024; 7748 else 7749 tileLayerPoolCapacity = 12 * 1024 * 1024; 7750#endif 7751 break; 7752 } 7753 case WebCacheModelDocumentBrowser: { 7754 // Page cache capacity (in pages) 7755 if (memSize >= 1024) 7756 pageCacheCapacity = 3; 7757 else if (memSize >= 512) 7758 pageCacheCapacity = 2; 7759 else if (memSize >= 256) 7760 pageCacheCapacity = 1; 7761 else 7762 pageCacheCapacity = 0; 7763 7764 // Object cache capacities (in bytes) 7765 if (memSize >= 4096) 7766 cacheTotalCapacity = 128 * 1024 * 1024; 7767 else if (memSize >= 2048) 7768 cacheTotalCapacity = 96 * 1024 * 1024; 7769 else if (memSize >= 1024) 7770 cacheTotalCapacity = 32 * 1024 * 1024; 7771 else if (memSize >= 512) 7772 cacheTotalCapacity = 16 * 1024 * 1024; 7773 7774 cacheMinDeadCapacity = cacheTotalCapacity / 8; 7775 cacheMaxDeadCapacity = cacheTotalCapacity / 4; 7776 7777 // Foundation memory cache capacity (in bytes) 7778 if (memSize >= 2048) 7779 nsurlCacheMemoryCapacity = 4 * 1024 * 1024; 7780 else if (memSize >= 1024) 7781 nsurlCacheMemoryCapacity = 2 * 1024 * 1024; 7782 else if (memSize >= 512) 7783 nsurlCacheMemoryCapacity = 1 * 1024 * 1024; 7784 else 7785 nsurlCacheMemoryCapacity = 512 * 1024; 7786 7787 // Foundation disk cache capacity (in bytes) 7788 if (diskFreeSize >= 16384) 7789 nsurlCacheDiskCapacity = 50 * 1024 * 1024; 7790 else if (diskFreeSize >= 8192) 7791 nsurlCacheDiskCapacity = 40 * 1024 * 1024; 7792 else if (diskFreeSize >= 4096) 7793 nsurlCacheDiskCapacity = 30 * 1024 * 1024; 7794 else 7795 nsurlCacheDiskCapacity = 20 * 1024 * 1024; 7796 7797#if PLATFORM(IOS) 7798 // TileCache layer pool capacity, in bytes. 7799 if (memSize >= 1024) 7800 tileLayerPoolCapacity = 24 * 1024 * 1024; 7801 else 7802 tileLayerPoolCapacity = 12 * 1024 * 1024; 7803#endif 7804 break; 7805 } 7806 case WebCacheModelPrimaryWebBrowser: { 7807 // Page cache capacity (in pages) 7808 // (Research indicates that value / page drops substantially after 3 pages.) 7809 if (memSize >= 2048) 7810 pageCacheCapacity = 5; 7811 else if (memSize >= 1024) 7812 pageCacheCapacity = 4; 7813 else if (memSize >= 512) 7814 pageCacheCapacity = 3; 7815 else if (memSize >= 256) 7816 pageCacheCapacity = 2; 7817 else 7818 pageCacheCapacity = 1; 7819 7820#if PLATFORM(IOS) 7821 // Cache page less aggressively in iOS to reduce the chance of being jettisoned. 7822 // FIXME (<rdar://problem/11779846>): Avoiding jettisoning should not have to require reducing the page cache capacity. 7823 // Reducing the capacity by 1 reduces overall back-forward performance. 7824 if (pageCacheCapacity > 0) 7825 pageCacheCapacity -= 1; 7826#endif 7827 7828 // Object cache capacities (in bytes) 7829 // (Testing indicates that value / MB depends heavily on content and 7830 // browsing pattern. Even growth above 128MB can have substantial 7831 // value / MB for some content / browsing patterns.) 7832 if (memSize >= 4096) 7833 cacheTotalCapacity = 192 * 1024 * 1024; 7834 else if (memSize >= 2048) 7835 cacheTotalCapacity = 128 * 1024 * 1024; 7836 else if (memSize >= 1024) 7837 cacheTotalCapacity = 64 * 1024 * 1024; 7838 else if (memSize >= 512) 7839 cacheTotalCapacity = 32 * 1024 * 1024; 7840 7841 cacheMinDeadCapacity = cacheTotalCapacity / 4; 7842 cacheMaxDeadCapacity = cacheTotalCapacity / 2; 7843 7844 // This code is here to avoid a PLT regression. We can remove it if we 7845 // can prove that the overall system gain would justify the regression. 7846 cacheMaxDeadCapacity = std::max<unsigned>(24, cacheMaxDeadCapacity); 7847 7848 deadDecodedDataDeletionInterval = std::chrono::seconds { 60 }; 7849 7850#if PLATFORM(IOS) 7851 if (memSize >= 1024) 7852 nsurlCacheMemoryCapacity = 16 * 1024 * 1024; 7853 else 7854 nsurlCacheMemoryCapacity = 8 * 1024 * 1024; 7855#else 7856 // Foundation memory cache capacity (in bytes) 7857 // (These values are small because WebCore does most caching itself.) 7858 if (memSize >= 1024) 7859 nsurlCacheMemoryCapacity = 4 * 1024 * 1024; 7860 else if (memSize >= 512) 7861 nsurlCacheMemoryCapacity = 2 * 1024 * 1024; 7862 else if (memSize >= 256) 7863 nsurlCacheMemoryCapacity = 1 * 1024 * 1024; 7864 else 7865 nsurlCacheMemoryCapacity = 512 * 1024; 7866#endif 7867 7868 // Foundation disk cache capacity (in bytes) 7869 if (diskFreeSize >= 16384) 7870 nsurlCacheDiskCapacity = 175 * 1024 * 1024; 7871 else if (diskFreeSize >= 8192) 7872 nsurlCacheDiskCapacity = 150 * 1024 * 1024; 7873 else if (diskFreeSize >= 4096) 7874 nsurlCacheDiskCapacity = 125 * 1024 * 1024; 7875 else if (diskFreeSize >= 2048) 7876 nsurlCacheDiskCapacity = 100 * 1024 * 1024; 7877 else if (diskFreeSize >= 1024) 7878 nsurlCacheDiskCapacity = 75 * 1024 * 1024; 7879 else 7880 nsurlCacheDiskCapacity = 50 * 1024 * 1024; 7881 7882#if PLATFORM(IOS) 7883 // TileCache layer pool capacity, in bytes. 7884 if (memSize >= 1024) 7885 tileLayerPoolCapacity = 48 * 1024 * 1024; 7886 else 7887 tileLayerPoolCapacity = 24 * 1024 * 1024; 7888#endif 7889 break; 7890 } 7891 default: 7892 ASSERT_NOT_REACHED(); 7893 }; 7894 7895 7896 // Don't shrink a big disk cache, since that would cause churn. 7897 nsurlCacheDiskCapacity = std::max(nsurlCacheDiskCapacity, [nsurlCache diskCapacity]); 7898 7899 memoryCache()->setCapacities(cacheMinDeadCapacity, cacheMaxDeadCapacity, cacheTotalCapacity); 7900 memoryCache()->setDeadDecodedDataDeletionInterval(deadDecodedDataDeletionInterval); 7901 pageCache()->setCapacity(pageCacheCapacity); 7902#if PLATFORM(IOS) 7903 pageCache()->setShouldClearBackingStores(true); 7904 nsurlCacheMemoryCapacity = std::max(nsurlCacheMemoryCapacity, [nsurlCache memoryCapacity]); 7905 CFURLCacheRef cfCache; 7906 if ([nsurlCache respondsToSelector:@selector(_CFURLCache)] && (cfCache = [nsurlCache _CFURLCache])) 7907 CFURLCacheSetMemoryCapacity(cfCache, nsurlCacheMemoryCapacity); 7908 else 7909 [nsurlCache setMemoryCapacity:nsurlCacheMemoryCapacity]; 7910#else 7911 [nsurlCache setMemoryCapacity:nsurlCacheMemoryCapacity]; 7912#endif 7913 [nsurlCache setDiskCapacity:nsurlCacheDiskCapacity]; 7914 7915#if PLATFORM(IOS) 7916 [WebView _setTileCacheLayerPoolCapacity:tileLayerPoolCapacity]; 7917#endif 7918 7919 s_cacheModel = cacheModel; 7920 s_didSetCacheModel = YES; 7921} 7922 7923+ (WebCacheModel)_cacheModel 7924{ 7925 return s_cacheModel; 7926} 7927 7928+ (BOOL)_didSetCacheModel 7929{ 7930 return s_didSetCacheModel; 7931} 7932 7933+ (WebCacheModel)_maxCacheModelInAnyInstance 7934{ 7935 WebCacheModel cacheModel = WebCacheModelDocumentViewer; 7936 NSEnumerator *enumerator = [(NSMutableSet *)allWebViewsSet objectEnumerator]; 7937 while (WebPreferences *preferences = [[enumerator nextObject] preferences]) 7938 cacheModel = std::max(cacheModel, [preferences cacheModel]); 7939 return cacheModel; 7940} 7941 7942+ (void)_cacheModelChangedNotification:(NSNotification *)notification 7943{ 7944#if PLATFORM(IOS) 7945 // This needs to happen on the Web Thread 7946 WebThreadRun(^{ 7947#endif 7948 WebPreferences *preferences = (WebPreferences *)[notification object]; 7949 ASSERT([preferences isKindOfClass:[WebPreferences class]]); 7950 7951 WebCacheModel cacheModel = [preferences cacheModel]; 7952 if (![self _didSetCacheModel] || cacheModel > [self _cacheModel]) 7953 [self _setCacheModel:cacheModel]; 7954 else if (cacheModel < [self _cacheModel]) 7955 [self _setCacheModel:std::max([[WebPreferences standardPreferences] cacheModel], [self _maxCacheModelInAnyInstance])]; 7956#if PLATFORM(IOS) 7957 }); 7958#endif 7959} 7960 7961+ (void)_preferencesRemovedNotification:(NSNotification *)notification 7962{ 7963 WebPreferences *preferences = (WebPreferences *)[notification object]; 7964 ASSERT([preferences isKindOfClass:[WebPreferences class]]); 7965 7966 if ([preferences cacheModel] == [self _cacheModel]) 7967 [self _setCacheModel:std::max([[WebPreferences standardPreferences] cacheModel], [self _maxCacheModelInAnyInstance])]; 7968} 7969 7970- (WebFrame *)_focusedFrame 7971{ 7972 NSResponder *resp = [[self window] firstResponder]; 7973 if (resp && [resp isKindOfClass:[NSView class]] && [(NSView *)resp isDescendantOf:[[self mainFrame] frameView]]) { 7974 WebFrameView *frameView = containingFrameView((NSView *)resp); 7975 ASSERT(frameView != nil); 7976 return [frameView webFrame]; 7977 } 7978 7979 return nil; 7980} 7981 7982- (BOOL)_isLoading 7983{ 7984 WebFrame *mainFrame = [self mainFrame]; 7985 return [[mainFrame _dataSource] isLoading] 7986 || [[mainFrame provisionalDataSource] isLoading]; 7987} 7988 7989- (WebFrameView *)_frameViewAtWindowPoint:(NSPoint)point 7990{ 7991 if (_private->closed) 7992 return nil; 7993#if !PLATFORM(IOS) 7994 NSView *view = [self hitTest:[[self superview] convertPoint:point fromView:nil]]; 7995#else 7996 //[WebView superview] on iOS is nil, don't do a convertPoint 7997 NSView *view = [self hitTest:point]; 7998#endif 7999 if (![view isDescendantOf:[[self mainFrame] frameView]]) 8000 return nil; 8001 WebFrameView *frameView = containingFrameView(view); 8002 ASSERT(frameView); 8003 return frameView; 8004} 8005 8006+ (void)_preflightSpellCheckerNow:(id)sender 8007{ 8008#if !PLATFORM(IOS) 8009 [[NSSpellChecker sharedSpellChecker] _preflightChosenSpellServer]; 8010#endif 8011} 8012 8013+ (void)_preflightSpellChecker 8014{ 8015#if !PLATFORM(IOS) 8016 // As AppKit does, we wish to delay tickling the shared spellchecker into existence on application launch. 8017 if ([NSSpellChecker sharedSpellCheckerExists]) { 8018 [self _preflightSpellCheckerNow:self]; 8019 } else { 8020 [self performSelector:@selector(_preflightSpellCheckerNow:) withObject:self afterDelay:2.0]; 8021 } 8022#endif 8023} 8024 8025- (BOOL)_continuousCheckingAllowed 8026{ 8027 static BOOL allowContinuousSpellChecking = YES; 8028 static BOOL readAllowContinuousSpellCheckingDefault = NO; 8029 if (!readAllowContinuousSpellCheckingDefault) { 8030 if ([[NSUserDefaults standardUserDefaults] objectForKey:@"NSAllowContinuousSpellChecking"]) { 8031 allowContinuousSpellChecking = [[NSUserDefaults standardUserDefaults] boolForKey:@"NSAllowContinuousSpellChecking"]; 8032 } 8033 readAllowContinuousSpellCheckingDefault = YES; 8034 } 8035 return allowContinuousSpellChecking; 8036} 8037 8038- (NSResponder *)_responderForResponderOperations 8039{ 8040 NSResponder *responder = [[self window] firstResponder]; 8041 WebFrameView *mainFrameView = [[self mainFrame] frameView]; 8042 8043 // If the current responder is outside of the webview, use our main frameView or its 8044 // document view. We also do this for subviews of self that are siblings of the main 8045 // frameView since clients might insert non-webview-related views there (see 4552713). 8046 if (responder != self && ![mainFrameView _web_firstResponderIsSelfOrDescendantView]) { 8047 responder = [mainFrameView documentView]; 8048 if (!responder) 8049 responder = mainFrameView; 8050 } 8051 return responder; 8052} 8053 8054#if !PLATFORM(IOS) 8055- (void)_openFrameInNewWindowFromMenu:(NSMenuItem *)sender 8056{ 8057 ASSERT_ARG(sender, [sender isKindOfClass:[NSMenuItem class]]); 8058 8059 NSDictionary *element = [sender representedObject]; 8060 ASSERT([element isKindOfClass:[NSDictionary class]]); 8061 8062 WebDataSource *dataSource = [(WebFrame *)[element objectForKey:WebElementFrameKey] dataSource]; 8063 NSURLRequest *request = [[dataSource request] copy]; 8064 ASSERT(request); 8065 8066 [self _openNewWindowWithRequest:request]; 8067 [request release]; 8068} 8069 8070- (void)_searchWithGoogleFromMenu:(id)sender 8071{ 8072 id documentView = [[[self selectedFrame] frameView] documentView]; 8073 if (![documentView conformsToProtocol:@protocol(WebDocumentText)]) { 8074 return; 8075 } 8076 8077 NSString *selectedString = [(id <WebDocumentText>)documentView selectedString]; 8078 if ([selectedString length] == 0) { 8079 return; 8080 } 8081 8082 NSPasteboard *pasteboard = [NSPasteboard pasteboardWithUniqueName]; 8083 [pasteboard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil]; 8084 NSMutableString *s = [selectedString mutableCopy]; 8085 const unichar nonBreakingSpaceCharacter = 0xA0; 8086 NSString *nonBreakingSpaceString = [NSString stringWithCharacters:&nonBreakingSpaceCharacter length:1]; 8087 [s replaceOccurrencesOfString:nonBreakingSpaceString withString:@" " options:0 range:NSMakeRange(0, [s length])]; 8088 [pasteboard setString:s forType:NSStringPboardType]; 8089 [s release]; 8090 8091 // FIXME: seems fragile to use the service by name, but this is what AppKit does 8092 NSPerformService(@"Search With Google", pasteboard); 8093} 8094 8095- (void)_searchWithSpotlightFromMenu:(id)sender 8096{ 8097 id documentView = [[[self selectedFrame] frameView] documentView]; 8098 if (![documentView conformsToProtocol:@protocol(WebDocumentText)]) 8099 return; 8100 8101 NSString *selectedString = [(id <WebDocumentText>)documentView selectedString]; 8102 if (![selectedString length]) 8103 return; 8104 8105 [[NSWorkspace sharedWorkspace] showSearchResultsForQueryString:selectedString]; 8106} 8107#endif // !PLATFORM(IOS) 8108 8109#if USE(GLIB) 8110- (void)_clearGlibLoopObserver 8111{ 8112 if (!_private->glibRunLoopObserver) 8113 return; 8114 8115 CFRunLoopObserverInvalidate(_private->glibRunLoopObserver); 8116 CFRelease(_private->glibRunLoopObserver); 8117 _private->glibRunLoopObserver = 0; 8118} 8119#endif 8120@end 8121 8122@implementation WebView (WebViewInternal) 8123 8124+ (BOOL)shouldIncludeInWebKitStatistics 8125{ 8126 return NO; 8127} 8128 8129- (BOOL)_becomingFirstResponderFromOutside 8130{ 8131 return _private->becomingFirstResponderFromOutside; 8132} 8133 8134#if ENABLE(ICONDATABASE) 8135- (void)_receivedIconChangedNotification:(NSNotification *)notification 8136{ 8137 // Get the URL for this notification 8138 NSDictionary *userInfo = [notification userInfo]; 8139 ASSERT([userInfo isKindOfClass:[NSDictionary class]]); 8140 NSString *urlString = [userInfo objectForKey:WebIconNotificationUserInfoURLKey]; 8141 ASSERT([urlString isKindOfClass:[NSString class]]); 8142 8143 // If that URL matches the current main frame, dispatch the delegate call, which will also unregister 8144 // us for this notification 8145 if ([[self mainFrameURL] isEqualTo:urlString]) 8146 [self _dispatchDidReceiveIconFromWebFrame:[self mainFrame]]; 8147} 8148 8149- (void)_registerForIconNotification:(BOOL)listen 8150{ 8151 if (listen) 8152 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_receivedIconChangedNotification:) name:WebIconDatabaseDidAddIconNotification object:nil]; 8153 else 8154 [[NSNotificationCenter defaultCenter] removeObserver:self name:WebIconDatabaseDidAddIconNotification object:nil]; 8155} 8156 8157- (void)_dispatchDidReceiveIconFromWebFrame:(WebFrame *)webFrame 8158{ 8159 // FIXME: This willChangeValueForKey call is too late, because the icon has already changed by now. 8160 [self _willChangeValueForKey:_WebMainFrameIconKey]; 8161 8162 // Since we definitely have an icon and are about to send out the delegate call for that, this WebView doesn't need to listen for the general 8163 // notification any longer 8164 [self _registerForIconNotification:NO]; 8165 8166 WebFrameLoadDelegateImplementationCache* cache = &_private->frameLoadDelegateImplementations; 8167 if (cache->didReceiveIconForFrameFunc) { 8168 Image* image = iconDatabase().synchronousIconForPageURL(core(webFrame)->document()->url().string(), IntSize(16, 16)); 8169 if (NSImage *icon = webGetNSImage(image, NSMakeSize(16, 16))) 8170 CallFrameLoadDelegate(cache->didReceiveIconForFrameFunc, self, @selector(webView:didReceiveIcon:forFrame:), icon, webFrame); 8171 } 8172 8173 [self _didChangeValueForKey:_WebMainFrameIconKey]; 8174} 8175#endif // ENABLE(ICONDATABASE) 8176 8177- (void)_addObject:(id)object forIdentifier:(unsigned long)identifier 8178{ 8179 ASSERT(!_private->identifierMap.contains(identifier)); 8180 8181 // If the identifier map is initially empty it means we're starting a load 8182 // of something. The semantic is that the web view should be around as long 8183 // as something is loading. Because of that we retain the web view. 8184 if (_private->identifierMap.isEmpty()) 8185 CFRetain(self); 8186 8187 _private->identifierMap.set(identifier, object); 8188} 8189 8190- (id)_objectForIdentifier:(unsigned long)identifier 8191{ 8192 return _private->identifierMap.get(identifier).get(); 8193} 8194 8195- (void)_removeObjectForIdentifier:(unsigned long)identifier 8196{ 8197 ASSERT(_private->identifierMap.contains(identifier)); 8198 _private->identifierMap.remove(identifier); 8199 8200 // If the identifier map is now empty it means we're no longer loading anything 8201 // and we should release the web view. Autorelease rather than release in order to 8202 // avoid re-entering this method beneath -dealloc with the same identifier. <rdar://problem/10523721> 8203 if (_private->identifierMap.isEmpty()) 8204 [self autorelease]; 8205} 8206 8207- (void)_retrieveKeyboardUIModeFromPreferences:(NSNotification *)notification 8208{ 8209 CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication); 8210 8211 Boolean keyExistsAndHasValidFormat; 8212 int mode = CFPreferencesGetAppIntegerValue(AppleKeyboardUIMode, kCFPreferencesCurrentApplication, &keyExistsAndHasValidFormat); 8213 8214 // The keyboard access mode has two bits: 8215 // Bit 0 is set if user can set the focus to menus, the dock, and various windows using the keyboard. 8216 // Bit 1 is set if controls other than text fields are included in the tab order (WebKit also always includes lists). 8217 _private->_keyboardUIMode = (mode & 0x2) ? KeyboardAccessFull : KeyboardAccessDefault; 8218#if !PLATFORM(IOS) 8219 // check for tabbing to links 8220 if ([_private->preferences tabsToLinks]) 8221 _private->_keyboardUIMode = (KeyboardUIMode)(_private->_keyboardUIMode | KeyboardAccessTabsToLinks); 8222#endif 8223} 8224 8225- (KeyboardUIMode)_keyboardUIMode 8226{ 8227 if (!_private->_keyboardUIModeAccessed) { 8228 _private->_keyboardUIModeAccessed = YES; 8229 8230 [self _retrieveKeyboardUIModeFromPreferences:nil]; 8231 8232#if !PLATFORM(IOS) 8233 [[NSDistributedNotificationCenter defaultCenter] 8234 addObserver:self selector:@selector(_retrieveKeyboardUIModeFromPreferences:) 8235 name:KeyboardUIModeDidChangeNotification object:nil]; 8236#endif 8237 8238 [[NSNotificationCenter defaultCenter] 8239 addObserver:self selector:@selector(_retrieveKeyboardUIModeFromPreferences:) 8240 name:WebPreferencesChangedInternalNotification object:nil]; 8241 } 8242 return _private->_keyboardUIMode; 8243} 8244 8245#if !PLATFORM(IOS) 8246- (void)_setInsertionPasteboard:(NSPasteboard *)pasteboard 8247{ 8248 _private->insertionPasteboard = pasteboard; 8249} 8250#endif 8251 8252- (Frame*)_mainCoreFrame 8253{ 8254 return (_private && _private->page) ? &_private->page->mainFrame() : 0; 8255} 8256 8257- (WebFrame *)_selectedOrMainFrame 8258{ 8259 WebFrame *result = [self selectedFrame]; 8260 if (result == nil) 8261 result = [self mainFrame]; 8262 return result; 8263} 8264 8265- (BOOL)_needsOneShotDrawingSynchronization 8266{ 8267 return _private->needsOneShotDrawingSynchronization; 8268} 8269 8270- (void)_setNeedsOneShotDrawingSynchronization:(BOOL)needsSynchronization 8271{ 8272 _private->needsOneShotDrawingSynchronization = needsSynchronization; 8273} 8274 8275/* 8276 The order of events with compositing updates is this: 8277 8278 Start of runloop End of runloop 8279 | | 8280 --|-------------------------------------------------------|-- 8281 ^ ^ ^ 8282 | | | 8283 NSWindow update, | CA commit 8284 NSView drawing | 8285 flush | 8286 layerSyncRunLoopObserverCallBack 8287 8288 To avoid flashing, we have to ensure that compositing changes (rendered via 8289 the CoreAnimation rendering display link) appear on screen at the same time 8290 as content painted into the window via the normal WebCore rendering path. 8291 8292 CoreAnimation will commit any layer changes at the end of the runloop via 8293 its "CA commit" observer. Those changes can then appear onscreen at any time 8294 when the display link fires, which can result in unsynchronized rendering. 8295 8296 To fix this, the GraphicsLayerCA code in WebCore does not change the CA 8297 layer tree during style changes and layout; it stores up all changes and 8298 commits them via flushCompositingState(). There are then two situations in 8299 which we can call flushCompositingState(): 8300 8301 1. When painting. FrameView::paintContents() makes a call to flushCompositingState(). 8302 8303 2. When style changes/layout have made changes to the layer tree which do not 8304 result in painting. In this case we need a run loop observer to do a 8305 flushCompositingState() at an appropriate time. The observer will keep firing 8306 until the time is right (essentially when there are no more pending layouts). 8307 8308*/ 8309bool LayerFlushController::flushLayers() 8310{ 8311#if PLATFORM(IOS) 8312 WebThreadLock(); 8313#endif 8314#if !PLATFORM(IOS) 8315 NSWindow *window = [m_webView window]; 8316 8317 // An NSWindow may not display in the next runloop cycle after dirtying due to delayed window display logic, 8318 // in which case this observer can fire first. So if the window is due for a display, don't commit 8319 // layer changes, otherwise they'll show on screen before the view drawing. 8320 bool viewsNeedDisplay; 8321#ifndef __LP64__ 8322 if (window && [window _wrapsCarbonWindow]) 8323 viewsNeedDisplay = HIViewGetNeedsDisplay(HIViewGetRoot(static_cast<WindowRef>([window windowRef]))); 8324 else 8325#endif 8326 viewsNeedDisplay = [window viewsNeedDisplay]; 8327 8328 if (viewsNeedDisplay) 8329 return false; 8330#endif 8331 8332#if PLATFORM(IOS) 8333 // Ensure fixed positions layers are where they should be. 8334 [m_webView _synchronizeCustomFixedPositionLayoutRect]; 8335#endif 8336 8337 [m_webView _viewWillDrawInternal]; 8338 8339 if ([m_webView _flushCompositingChanges]) { 8340#if !PLATFORM(IOS) 8341 // AppKit may have disabled screen updates, thinking an upcoming window flush will re-enable them. 8342 // In case setNeedsDisplayInRect() has prevented the window from needing to be flushed, re-enable screen 8343 // updates here. 8344 if (![window isFlushWindowDisabled]) 8345 [window _enableScreenUpdatesIfNeeded]; 8346#endif 8347 8348 return true; 8349 } 8350 8351 return false; 8352} 8353 8354- (void)_scheduleCompositingLayerFlush 8355{ 8356#if PLATFORM(IOS) 8357 if (_private->closing) 8358 return; 8359#endif 8360 8361 if (!_private->layerFlushController) 8362 _private->layerFlushController = LayerFlushController::create(self); 8363 _private->layerFlushController->scheduleLayerFlush(); 8364} 8365 8366- (BOOL)_flushCompositingChanges 8367{ 8368 Frame* frame = [self _mainCoreFrame]; 8369 if (frame && frame->view()) 8370 return frame->view()->flushCompositingStateIncludingSubframes(); 8371 8372 return YES; 8373} 8374 8375#if PLATFORM(IOS) 8376- (void)_scheduleLayerFlushForPendingTileCacheRepaint 8377{ 8378 Frame* coreFrame = [self _mainCoreFrame]; 8379 if (FrameView* view = coreFrame->view()) 8380 view->scheduleLayerFlushAllowingThrottling(); 8381} 8382#endif 8383 8384#if ENABLE(VIDEO) 8385- (void)_enterFullscreenForNode:(WebCore::Node*)node 8386{ 8387 ASSERT(isHTMLVideoElement(node)); 8388 HTMLMediaElement* videoElement = toHTMLMediaElement(node); 8389 8390 if (_private->fullscreenController) { 8391 if ([_private->fullscreenController mediaElement] == videoElement) { 8392 // The backend may just warn us that the underlaying plaftormMovie() 8393 // has changed. Just force an update. 8394 [_private->fullscreenController setMediaElement:videoElement]; 8395 return; // No more to do. 8396 } 8397 8398 // First exit Fullscreen for the old mediaElement. 8399 [_private->fullscreenController mediaElement]->exitFullscreen(); 8400 // This previous call has to trigger _exitFullscreen, 8401 // which has to clear _private->fullscreenController. 8402 ASSERT(!_private->fullscreenController); 8403 } 8404 if (!_private->fullscreenController) { 8405 _private->fullscreenController = [[WebVideoFullscreenController alloc] init]; 8406 [_private->fullscreenController setMediaElement:videoElement]; 8407#if PLATFORM(IOS) 8408 [_private->fullscreenController enterFullscreen:(UIView *)[[[self window] hostLayer] delegate]]; 8409#else 8410 [_private->fullscreenController enterFullscreen:[[self window] screen]]; 8411#endif 8412 } 8413 else 8414 [_private->fullscreenController setMediaElement:videoElement]; 8415} 8416 8417- (void)_exitFullscreen 8418{ 8419 if (!_private->fullscreenController) 8420 return; 8421 [_private->fullscreenController exitFullscreen]; 8422 [_private->fullscreenController release]; 8423 _private->fullscreenController = nil; 8424} 8425 8426#endif // ENABLE(VIDEO) && !PLATFORM(IOS) 8427 8428#if ENABLE(FULLSCREEN_API) && !PLATFORM(IOS) 8429- (BOOL)_supportsFullScreenForElement:(const WebCore::Element*)element withKeyboard:(BOOL)withKeyboard 8430{ 8431 if (![[WebPreferences standardPreferences] fullScreenEnabled]) 8432 return NO; 8433 8434 return !withKeyboard; 8435} 8436 8437- (void)_enterFullScreenForElement:(WebCore::Element*)element 8438{ 8439 if (!_private->newFullscreenController) 8440 _private->newFullscreenController = [[WebFullScreenController alloc] init]; 8441 8442 [_private->newFullscreenController setElement:element]; 8443 [_private->newFullscreenController setWebView:self]; 8444 [_private->newFullscreenController enterFullScreen:[[self window] screen]]; 8445} 8446 8447- (void)_exitFullScreenForElement:(WebCore::Element*)element 8448{ 8449 if (!_private->newFullscreenController) 8450 return; 8451 [_private->newFullscreenController exitFullScreen]; 8452} 8453#endif 8454 8455#if USE(GLIB) 8456 8457static void glibContextIterationCallback(CFRunLoopObserverRef, CFRunLoopActivity, void*) 8458{ 8459 g_main_context_iteration(0, FALSE); 8460} 8461 8462- (void)_scheduleGlibContextIterations 8463{ 8464 if (_private->glibRunLoopObserver) 8465 return; 8466 8467 NSRunLoop* myRunLoop = [NSRunLoop currentRunLoop]; 8468 8469 // Create a run loop observer and attach it to the run loop. 8470 CFRunLoopObserverContext context = {0, self, 0, 0, 0}; 8471 _private->glibRunLoopObserver = CFRunLoopObserverCreate(kCFAllocatorDefault, kCFRunLoopBeforeWaiting, YES, 0, &glibContextIterationCallback, &context); 8472 8473 if (_private->glibRunLoopObserver) { 8474 CFRunLoopRef cfLoop = [myRunLoop getCFRunLoop]; 8475 CFRunLoopAddObserver(cfLoop, _private->glibRunLoopObserver, kCFRunLoopDefaultMode); 8476 } 8477 8478} 8479#endif 8480 8481#if USE(AUTOCORRECTION_PANEL) 8482- (void)handleAcceptedAlternativeText:(NSString*)text 8483{ 8484 WebFrame *webFrame = [self _selectedOrMainFrame]; 8485 Frame* coreFrame = core(webFrame); 8486 if (coreFrame) 8487 coreFrame->editor().handleAlternativeTextUIResult(text); 8488} 8489#endif 8490 8491#if USE(DICTATION_ALTERNATIVES) 8492- (void)_getWebCoreDictationAlternatives:(Vector<DictationAlternative>&)alternatives fromTextAlternatives:(const Vector<TextAlternativeWithRange>&)alternativesWithRange 8493{ 8494 for (size_t i = 0; i < alternativesWithRange.size(); ++i) { 8495 const TextAlternativeWithRange& alternativeWithRange = alternativesWithRange[i]; 8496 uint64_t dictationContext = _private->m_alternativeTextUIController->addAlternatives(alternativeWithRange.alternatives); 8497 if (dictationContext) 8498 alternatives.append(DictationAlternative(alternativeWithRange.range.location, alternativeWithRange.range.length, dictationContext)); 8499 } 8500} 8501 8502- (void)_showDictationAlternativeUI:(const WebCore::FloatRect&)boundingBoxOfDictatedText forDictationContext:(uint64_t)dictationContext 8503{ 8504 _private->m_alternativeTextUIController->showAlternatives(self, [self _convertRectFromRootView:boundingBoxOfDictatedText], dictationContext, ^(NSString* acceptedAlternative) { 8505 [self handleAcceptedAlternativeText:acceptedAlternative]; 8506 }); 8507} 8508 8509- (void)_removeDictationAlternatives:(uint64_t)dictationContext 8510{ 8511 _private->m_alternativeTextUIController->removeAlternatives(dictationContext); 8512} 8513 8514- (Vector<String>)_dictationAlternatives:(uint64_t)dictationContext 8515{ 8516 return _private->m_alternativeTextUIController->alternativesForContext(dictationContext); 8517} 8518#endif 8519 8520- (NSPoint)_convertPointFromRootView:(NSPoint)point 8521{ 8522 return NSMakePoint(point.x, [self bounds].size.height - point.y); 8523} 8524 8525- (NSRect)_convertRectFromRootView:(NSRect)rect 8526{ 8527 return NSMakeRect(rect.origin.x, [self bounds].size.height - rect.origin.y - rect.size.height, rect.size.width, rect.size.height); 8528} 8529 8530@end 8531 8532@implementation WebView (WebViewDeviceOrientation) 8533 8534- (void)_setDeviceOrientationProvider:(id<WebDeviceOrientationProvider>)deviceOrientationProvider 8535{ 8536 if (_private) 8537 _private->m_deviceOrientationProvider = deviceOrientationProvider; 8538} 8539 8540- (id<WebDeviceOrientationProvider>)_deviceOrientationProvider 8541{ 8542 if (_private) 8543 return _private->m_deviceOrientationProvider; 8544 return nil; 8545} 8546 8547@end 8548 8549#if ENABLE(MEDIA_STREAM) 8550@implementation WebView (WebViewUserMedia) 8551 8552- (void)_setUserMediaClient:(id<WebUserMediaClient>)userMediaClient 8553{ 8554 if (_private) 8555 _private->m_userMediaClient = userMediaClient; 8556} 8557 8558- (id<WebUserMediaClient>)_userMediaClient 8559{ 8560 if (_private) 8561 return _private->m_userMediaClient; 8562 return nil; 8563} 8564@end 8565#endif 8566 8567@implementation WebView (WebViewGeolocation) 8568 8569- (void)_setGeolocationProvider:(id<WebGeolocationProvider>)geolocationProvider 8570{ 8571 if (_private) 8572 _private->_geolocationProvider = geolocationProvider; 8573} 8574 8575- (id<WebGeolocationProvider>)_geolocationProvider 8576{ 8577 if (_private) 8578 return _private->_geolocationProvider; 8579 return nil; 8580} 8581 8582- (void)_geolocationDidChangePosition:(WebGeolocationPosition *)position 8583{ 8584#if ENABLE(GEOLOCATION) 8585 if (_private && _private->page) 8586 WebCore::GeolocationController::from(_private->page)->positionChanged(core(position)); 8587#endif // ENABLE(GEOLOCATION) 8588} 8589 8590- (void)_geolocationDidFailWithMessage:(NSString *)errorMessage 8591{ 8592#if ENABLE(GEOLOCATION) 8593 if (_private && _private->page) { 8594 RefPtr<GeolocationError> geolocatioError = GeolocationError::create(GeolocationError::PositionUnavailable, errorMessage); 8595 WebCore::GeolocationController::from(_private->page)->errorOccurred(geolocatioError.get()); 8596 } 8597#endif // ENABLE(GEOLOCATION) 8598} 8599 8600#if PLATFORM(IOS) 8601- (void)_resetAllGeolocationPermission 8602{ 8603#if ENABLE(GEOLOCATION) 8604 Frame* frame = [self _mainCoreFrame]; 8605 if (frame) 8606 frame->resetAllGeolocationPermission(); 8607#endif 8608} 8609#endif 8610 8611@end 8612 8613@implementation WebView (WebViewNotification) 8614- (void)_setNotificationProvider:(id<WebNotificationProvider>)notificationProvider 8615{ 8616 if (_private && !_private->_notificationProvider) { 8617 _private->_notificationProvider = notificationProvider; 8618 [_private->_notificationProvider registerWebView:self]; 8619 } 8620} 8621 8622- (id<WebNotificationProvider>)_notificationProvider 8623{ 8624 if (_private) 8625 return _private->_notificationProvider; 8626 return nil; 8627} 8628 8629- (void)_notificationDidShow:(uint64_t)notificationID 8630{ 8631 [[self _notificationProvider] webView:self didShowNotification:notificationID]; 8632} 8633 8634- (void)_notificationDidClick:(uint64_t)notificationID 8635{ 8636 [[self _notificationProvider] webView:self didClickNotification:notificationID]; 8637} 8638 8639- (void)_notificationsDidClose:(NSArray *)notificationIDs 8640{ 8641 [[self _notificationProvider] webView:self didCloseNotifications:notificationIDs]; 8642} 8643 8644- (uint64_t)_notificationIDForTesting:(JSValueRef)jsNotification 8645{ 8646#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS) 8647 JSContextRef context = [[self mainFrame] globalContext]; 8648 WebCore::Notification* notification = toNotification(toJS(toJS(context), jsNotification)); 8649 return static_cast<WebNotificationClient*>(NotificationController::clientFrom(_private->page))->notificationIDForTesting(notification); 8650#else 8651 return 0; 8652#endif 8653} 8654@end 8655 8656#if PLATFORM(IOS) 8657@implementation WebView (WebViewIOSPDF) 8658 8659+ (Class)_getPDFRepresentationClass 8660{ 8661 if (s_pdfRepresentationClass) 8662 return s_pdfRepresentationClass; 8663 return [WebPDFView class]; // This is WebPDFRepresentation for PLATFORM(MAC). 8664} 8665 8666+ (void)_setPDFRepresentationClass:(Class)pdfRepresentationClass 8667{ 8668 s_pdfRepresentationClass = pdfRepresentationClass; 8669} 8670 8671+ (Class)_getPDFViewClass 8672{ 8673 if (s_pdfViewClass) 8674 return s_pdfViewClass; 8675 return [WebPDFView class]; 8676} 8677 8678+ (void)_setPDFViewClass:(Class)pdfViewClass 8679{ 8680 s_pdfViewClass = pdfViewClass; 8681} 8682 8683@end 8684#endif 8685 8686@implementation WebView (WebViewFullScreen) 8687 8688- (NSView*)fullScreenPlaceholderView 8689{ 8690#if ENABLE(FULLSCREEN_API) 8691 if (_private->newFullscreenController && [_private->newFullscreenController isFullScreen]) 8692 return [_private->newFullscreenController webViewPlaceholder]; 8693#endif 8694 return nil; 8695} 8696 8697@end 8698 8699void WebInstallMemoryPressureHandler(void) 8700{ 8701 memoryPressureHandler().install(); 8702} 8703