1/* 2 * Copyright (C) 2005-2012 Apple Inc. All rights reserved. 3 * Copyright (C) 2006 David Smith (catfish.man@gmail.com) 4 * Copyright (C) 2010 Igalia S.L 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 16 * its contributors may be used to endorse or promote products derived 17 * from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31#import "WebViewInternal.h" 32#import "WebViewData.h" 33 34#import "DOMCSSStyleDeclarationInternal.h" 35#import "DOMDocumentInternal.h" 36#import "DOMNodeInternal.h" 37#import "DOMRangeInternal.h" 38#import "WebAlternativeTextClient.h" 39#import "WebApplicationCache.h" 40#import "WebBackForwardListInternal.h" 41#import "WebBaseNetscapePluginView.h" 42#import "WebCache.h" 43#import "WebChromeClient.h" 44#import "WebContextMenuClient.h" 45#import "WebDOMOperationsPrivate.h" 46#import "WebDataSourceInternal.h" 47#import "WebDatabaseManagerPrivate.h" 48#import "WebDefaultEditingDelegate.h" 49#import "WebDefaultPolicyDelegate.h" 50#import "WebDefaultUIDelegate.h" 51#import "WebDelegateImplementationCaching.h" 52#import "WebDeviceOrientationClient.h" 53#import "WebDeviceOrientationProvider.h" 54#import "WebDocument.h" 55#import "WebDocumentInternal.h" 56#import "WebDownload.h" 57#import "WebDownloadInternal.h" 58#import "WebDragClient.h" 59#import "WebDynamicScrollBarsViewInternal.h" 60#import "WebEditingDelegate.h" 61#import "WebEditorClient.h" 62#import "WebFormDelegatePrivate.h" 63#import "WebFrameInternal.h" 64#import "WebFrameNetworkingContext.h" 65#import "WebFrameViewInternal.h" 66#import "WebFullScreenController.h" 67#import "WebGeolocationClient.h" 68#import "WebGeolocationPositionInternal.h" 69#import "WebHTMLRepresentation.h" 70#import "WebHTMLViewInternal.h" 71#import "WebHistoryItemInternal.h" 72#import "WebIconDatabaseInternal.h" 73#import "WebInspector.h" 74#import "WebInspectorClient.h" 75#import "WebKitErrors.h" 76#import "WebKitFullScreenListener.h" 77#import "WebKitLogging.h" 78#import "WebKitNSStringExtras.h" 79#import "WebKitStatisticsPrivate.h" 80#import "WebKitSystemBits.h" 81#import "WebKitVersionChecks.h" 82#import "WebLocalizableStrings.h" 83#import "WebNSDataExtras.h" 84#import "WebNSDataExtrasPrivate.h" 85#import "WebNSDictionaryExtras.h" 86#import "WebNSEventExtras.h" 87#import "WebNSObjectExtras.h" 88#import "WebNSPasteboardExtras.h" 89#import "WebNSPrintOperationExtras.h" 90#import "WebNSURLExtras.h" 91#import "WebNSURLRequestExtras.h" 92#import "WebNSViewExtras.h" 93#import "WebNodeHighlight.h" 94#import "WebNotificationClient.h" 95#import "WebPDFView.h" 96#import "WebPanelAuthenticationHandler.h" 97#import "WebPlatformStrategies.h" 98#import "WebPluginDatabase.h" 99#import "WebPolicyDelegate.h" 100#import "WebPreferenceKeysPrivate.h" 101#import "WebPreferencesPrivate.h" 102#import "WebScriptDebugDelegate.h" 103#import "WebScriptWorldInternal.h" 104#import "WebStorageManagerInternal.h" 105#import "WebSystemInterface.h" 106#import "WebTextCompletionController.h" 107#import "WebTextIterator.h" 108#import "WebUIDelegate.h" 109#import "WebUIDelegatePrivate.h" 110#import <CoreFoundation/CFSet.h> 111#import <Foundation/NSURLConnection.h> 112#import <JavaScriptCore/APICast.h> 113#import <JavaScriptCore/JSValueRef.h> 114#import <WebCore/AlternativeTextUIController.h> 115#import <WebCore/AnimationController.h> 116#import <WebCore/ApplicationCacheStorage.h> 117#import <WebCore/BackForwardListImpl.h> 118#import <WebCore/MemoryCache.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/DragSession.h> 127#import <WebCore/Editor.h> 128#import <WebCore/EventHandler.h> 129#import <WebCore/ExceptionHandlers.h> 130#import <WebCore/FocusController.h> 131#import <WebCore/Frame.h> 132#import <WebCore/FrameLoader.h> 133#import <WebCore/FrameSelection.h> 134#import <WebCore/FrameTree.h> 135#import <WebCore/FrameView.h> 136#import <WebCore/GCController.h> 137#import <WebCore/GeolocationController.h> 138#import <WebCore/GeolocationError.h> 139#import <WebCore/HTMLMediaElement.h> 140#import <WebCore/HTMLNames.h> 141#import <WebCore/HistoryController.h> 142#import <WebCore/HistoryItem.h> 143#import <WebCore/IconDatabase.h> 144#import <WebCore/InitializeLogging.h> 145#import <WebCore/JSCSSStyleDeclaration.h> 146#import <WebCore/JSDocument.h> 147#import <WebCore/JSElement.h> 148#import <WebCore/JSNodeList.h> 149#import <WebCore/JSNotification.h> 150#import <WebCore/MemoryPressureHandler.h> 151#import <WebCore/MIMETypeRegistry.h> 152#import <WebCore/NodeList.h> 153#import <WebCore/Notification.h> 154#import <WebCore/NotificationController.h> 155#import <WebCore/Page.h> 156#import <WebCore/PageCache.h> 157#import <WebCore/PageGroup.h> 158#import <WebCore/PlatformEventFactoryMac.h> 159#import <WebCore/ProgressTracker.h> 160#import <WebCore/RenderView.h> 161#import <WebCore/RenderWidget.h> 162#import <WebCore/ResourceHandle.h> 163#import <WebCore/ResourceLoadScheduler.h> 164#import <WebCore/ResourceRequest.h> 165#import <WebCore/RunLoop.h> 166#import <WebCore/RuntimeApplicationChecks.h> 167#import <WebCore/RuntimeEnabledFeatures.h> 168#import <WebCore/SchemeRegistry.h> 169#import <WebCore/ScriptController.h> 170#import <WebCore/ScriptValue.h> 171#import <WebCore/SecurityOrigin.h> 172#import <WebCore/SecurityPolicy.h> 173#import <WebCore/Settings.h> 174#import <WebCore/StylePropertySet.h> 175#import <WebCore/SystemVersionMac.h> 176#import <WebCore/TextResourceDecoder.h> 177#import <WebCore/ThreadCheck.h> 178#import <WebCore/WebCoreObjCExtras.h> 179#import <WebCore/WebCoreView.h> 180#import <WebCore/WebVideoFullscreenController.h> 181#import <WebCore/Widget.h> 182#import <WebKit/DOM.h> 183#import <WebKit/DOMExtensions.h> 184#import <WebKit/DOMPrivate.h> 185#import <WebKitSystemInterface.h> 186#import <mach-o/dyld.h> 187#import <objc/objc-auto.h> 188#import <objc/runtime.h> 189#import <runtime/ArrayPrototype.h> 190#import <runtime/DateInstance.h> 191#import <runtime/InitializeThreading.h> 192#import <runtime/JSLock.h> 193#import <runtime/JSCJSValue.h> 194#import <wtf/Assertions.h> 195#import <wtf/HashTraits.h> 196#import <wtf/MainThread.h> 197#import <wtf/ObjcRuntimeExtras.h> 198#import <wtf/RefCountedLeakCounter.h> 199#import <wtf/RefPtr.h> 200#import <wtf/StdLibExtras.h> 201 202#if ENABLE(DASHBOARD_SUPPORT) 203#import <WebKit/WebDashboardRegion.h> 204#endif 205 206#if USE(GLIB) 207#import <glib.h> 208#endif 209 210@interface NSSpellChecker (WebNSSpellCheckerDetails) 211- (void)_preflightChosenSpellServer; 212@end 213 214@interface NSView (WebNSViewDetails) 215- (NSView *)_hitTest:(NSPoint *)aPoint dragTypes:(NSSet *)types; 216- (void)_autoscrollForDraggingInfo:(id)dragInfo timeDelta:(NSTimeInterval)repeatDelta; 217- (BOOL)_shouldAutoscrollForDraggingInfo:(id)dragInfo; 218@end 219 220@interface NSWindow (WebNSWindowDetails) 221- (id)_oldFirstResponderBeforeBecoming; 222- (void)_enableScreenUpdatesIfNeeded; 223- (BOOL)_wrapsCarbonWindow; 224- (BOOL)_hasKeyAppearance; 225@end 226 227using namespace WebCore; 228using namespace JSC; 229 230#if defined(__ppc__) || defined(__ppc64__) 231#define PROCESSOR "PPC" 232#elif defined(__i386__) || defined(__x86_64__) 233#define PROCESSOR "Intel" 234#else 235#error Unknown architecture 236#endif 237 238#define FOR_EACH_RESPONDER_SELECTOR(macro) \ 239macro(alignCenter) \ 240macro(alignJustified) \ 241macro(alignLeft) \ 242macro(alignRight) \ 243macro(capitalizeWord) \ 244macro(centerSelectionInVisibleArea) \ 245macro(changeAttributes) \ 246macro(changeBaseWritingDirection) \ 247macro(changeBaseWritingDirectionToLTR) \ 248macro(changeBaseWritingDirectionToRTL) \ 249macro(changeColor) \ 250macro(changeDocumentBackgroundColor) \ 251macro(changeFont) \ 252macro(changeSpelling) \ 253macro(checkSpelling) \ 254macro(complete) \ 255macro(copy) \ 256macro(copyFont) \ 257macro(cut) \ 258macro(delete) \ 259macro(deleteBackward) \ 260macro(deleteBackwardByDecomposingPreviousCharacter) \ 261macro(deleteForward) \ 262macro(deleteToBeginningOfLine) \ 263macro(deleteToBeginningOfParagraph) \ 264macro(deleteToEndOfLine) \ 265macro(deleteToEndOfParagraph) \ 266macro(deleteToMark) \ 267macro(deleteWordBackward) \ 268macro(deleteWordForward) \ 269macro(ignoreSpelling) \ 270macro(indent) \ 271macro(insertBacktab) \ 272macro(insertLineBreak) \ 273macro(insertNewline) \ 274macro(insertNewlineIgnoringFieldEditor) \ 275macro(insertParagraphSeparator) \ 276macro(insertTab) \ 277macro(insertTabIgnoringFieldEditor) \ 278macro(lowercaseWord) \ 279macro(makeBaseWritingDirectionLeftToRight) \ 280macro(makeBaseWritingDirectionRightToLeft) \ 281macro(makeTextWritingDirectionLeftToRight) \ 282macro(makeTextWritingDirectionNatural) \ 283macro(makeTextWritingDirectionRightToLeft) \ 284macro(moveBackward) \ 285macro(moveBackwardAndModifySelection) \ 286macro(moveDown) \ 287macro(moveDownAndModifySelection) \ 288macro(moveForward) \ 289macro(moveForwardAndModifySelection) \ 290macro(moveLeft) \ 291macro(moveLeftAndModifySelection) \ 292macro(moveParagraphBackwardAndModifySelection) \ 293macro(moveParagraphForwardAndModifySelection) \ 294macro(moveRight) \ 295macro(moveRightAndModifySelection) \ 296macro(moveToBeginningOfDocument) \ 297macro(moveToBeginningOfDocumentAndModifySelection) \ 298macro(moveToBeginningOfLine) \ 299macro(moveToBeginningOfLineAndModifySelection) \ 300macro(moveToBeginningOfParagraph) \ 301macro(moveToBeginningOfParagraphAndModifySelection) \ 302macro(moveToBeginningOfSentence) \ 303macro(moveToBeginningOfSentenceAndModifySelection) \ 304macro(moveToEndOfDocument) \ 305macro(moveToEndOfDocumentAndModifySelection) \ 306macro(moveToEndOfLine) \ 307macro(moveToEndOfLineAndModifySelection) \ 308macro(moveToEndOfParagraph) \ 309macro(moveToEndOfParagraphAndModifySelection) \ 310macro(moveToEndOfSentence) \ 311macro(moveToEndOfSentenceAndModifySelection) \ 312macro(moveToLeftEndOfLine) \ 313macro(moveToLeftEndOfLineAndModifySelection) \ 314macro(moveToRightEndOfLine) \ 315macro(moveToRightEndOfLineAndModifySelection) \ 316macro(moveUp) \ 317macro(moveUpAndModifySelection) \ 318macro(moveWordBackward) \ 319macro(moveWordBackwardAndModifySelection) \ 320macro(moveWordForward) \ 321macro(moveWordForwardAndModifySelection) \ 322macro(moveWordLeft) \ 323macro(moveWordLeftAndModifySelection) \ 324macro(moveWordRight) \ 325macro(moveWordRightAndModifySelection) \ 326macro(orderFrontSubstitutionsPanel) \ 327macro(outdent) \ 328macro(overWrite) \ 329macro(pageDown) \ 330macro(pageDownAndModifySelection) \ 331macro(pageUp) \ 332macro(pageUpAndModifySelection) \ 333macro(paste) \ 334macro(pasteAsPlainText) \ 335macro(pasteAsRichText) \ 336macro(pasteFont) \ 337macro(performFindPanelAction) \ 338macro(scrollLineDown) \ 339macro(scrollLineUp) \ 340macro(scrollPageDown) \ 341macro(scrollPageUp) \ 342macro(scrollToBeginningOfDocument) \ 343macro(scrollToEndOfDocument) \ 344macro(selectAll) \ 345macro(selectLine) \ 346macro(selectParagraph) \ 347macro(selectSentence) \ 348macro(selectToMark) \ 349macro(selectWord) \ 350macro(setMark) \ 351macro(showGuessPanel) \ 352macro(startSpeaking) \ 353macro(stopSpeaking) \ 354macro(subscript) \ 355macro(superscript) \ 356macro(swapWithMark) \ 357macro(takeFindStringFromSelection) \ 358macro(toggleBaseWritingDirection) \ 359macro(transpose) \ 360macro(underline) \ 361macro(unscript) \ 362macro(uppercaseWord) \ 363macro(yank) \ 364macro(yankAndSelect) \ 365 366#define WebKitOriginalTopPrintingMarginKey @"WebKitOriginalTopMargin" 367#define WebKitOriginalBottomPrintingMarginKey @"WebKitOriginalBottomMargin" 368 369#define KeyboardUIModeDidChangeNotification @"com.apple.KeyboardUIModeDidChange" 370#define AppleKeyboardUIMode CFSTR("AppleKeyboardUIMode") 371#define UniversalAccessDomain CFSTR("com.apple.universalaccess") 372 373static BOOL s_didSetCacheModel; 374static WebCacheModel s_cacheModel = WebCacheModelDocumentViewer; 375 376#ifndef NDEBUG 377static const char webViewIsOpen[] = "At least one WebView is still open."; 378#endif 379 380@interface NSObject (WebValidateWithoutDelegate) 381- (BOOL)validateUserInterfaceItemWithoutDelegate:(id <NSValidatedUserInterfaceItem>)item; 382@end 383 384@interface _WebSafeForwarder : NSObject 385{ 386 id target; // Non-retained. Don't retain delegates. 387 id defaultTarget; 388} 389- (id)initWithTarget:(id)target defaultTarget:(id)defaultTarget; 390@end 391 392FindOptions coreOptions(WebFindOptions options) 393{ 394 return (options & WebFindOptionsCaseInsensitive ? CaseInsensitive : 0) 395 | (options & WebFindOptionsAtWordStarts ? AtWordStarts : 0) 396 | (options & WebFindOptionsTreatMedialCapitalAsWordStart ? TreatMedialCapitalAsWordStart : 0) 397 | (options & WebFindOptionsBackwards ? Backwards : 0) 398 | (options & WebFindOptionsWrapAround ? WrapAround : 0) 399 | (options & WebFindOptionsStartInSelection ? StartInSelection : 0); 400} 401 402LayoutMilestones coreLayoutMilestones(WebLayoutMilestones milestones) 403{ 404 return (milestones & WebDidFirstLayout ? DidFirstLayout : 0) 405 | (milestones & WebDidFirstVisuallyNonEmptyLayout ? DidFirstVisuallyNonEmptyLayout : 0) 406 | (milestones & WebDidHitRelevantRepaintedObjectsAreaThreshold ? DidHitRelevantRepaintedObjectsAreaThreshold : 0); 407} 408 409WebLayoutMilestones kitLayoutMilestones(LayoutMilestones milestones) 410{ 411 return (milestones & DidFirstLayout ? WebDidFirstLayout : 0) 412 | (milestones & DidFirstVisuallyNonEmptyLayout ? WebDidFirstVisuallyNonEmptyLayout : 0) 413 | (milestones & DidHitRelevantRepaintedObjectsAreaThreshold ? WebDidHitRelevantRepaintedObjectsAreaThreshold : 0); 414} 415 416static PageVisibilityState core(WebPageVisibilityState visibilityState) 417{ 418 switch (visibilityState) { 419 case WebPageVisibilityStateVisible: 420 return PageVisibilityStateVisible; 421 case WebPageVisibilityStateHidden: 422 return PageVisibilityStateHidden; 423 case WebPageVisibilityStatePrerender: 424 return PageVisibilityStatePrerender; 425 case WebPageVisibilityStateUnloaded: 426 return PageVisibilityStateUnloaded; 427 } 428 429 ASSERT_NOT_REACHED(); 430 return PageVisibilityStateVisible; 431} 432 433@interface WebView (WebFileInternal) 434- (float)_deviceScaleFactor; 435- (BOOL)_isLoading; 436- (WebFrameView *)_frameViewAtWindowPoint:(NSPoint)point; 437- (WebFrame *)_focusedFrame; 438+ (void)_preflightSpellChecker; 439- (BOOL)_continuousCheckingAllowed; 440- (NSResponder *)_responderForResponderOperations; 441#if USE(GLIB) 442- (void)_clearGlibLoopObserver; 443#endif 444@end 445 446NSString *WebElementDOMNodeKey = @"WebElementDOMNode"; 447NSString *WebElementFrameKey = @"WebElementFrame"; 448NSString *WebElementImageKey = @"WebElementImage"; 449NSString *WebElementImageAltStringKey = @"WebElementImageAltString"; 450NSString *WebElementImageRectKey = @"WebElementImageRect"; 451NSString *WebElementImageURLKey = @"WebElementImageURL"; 452NSString *WebElementIsSelectedKey = @"WebElementIsSelected"; 453NSString *WebElementLinkLabelKey = @"WebElementLinkLabel"; 454NSString *WebElementLinkTargetFrameKey = @"WebElementTargetFrame"; 455NSString *WebElementLinkTitleKey = @"WebElementLinkTitle"; 456NSString *WebElementLinkURLKey = @"WebElementLinkURL"; 457NSString *WebElementMediaURLKey = @"WebElementMediaURL"; 458NSString *WebElementSpellingToolTipKey = @"WebElementSpellingToolTip"; 459NSString *WebElementTitleKey = @"WebElementTitle"; 460NSString *WebElementLinkIsLiveKey = @"WebElementLinkIsLive"; 461NSString *WebElementIsInScrollBarKey = @"WebElementIsInScrollBar"; 462NSString *WebElementIsContentEditableKey = @"WebElementIsContentEditableKey"; 463 464NSString *WebViewProgressStartedNotification = @"WebProgressStartedNotification"; 465NSString *WebViewProgressEstimateChangedNotification = @"WebProgressEstimateChangedNotification"; 466NSString *WebViewProgressFinishedNotification = @"WebProgressFinishedNotification"; 467 468NSString * const WebViewDidBeginEditingNotification = @"WebViewDidBeginEditingNotification"; 469NSString * const WebViewDidChangeNotification = @"WebViewDidChangeNotification"; 470NSString * const WebViewDidEndEditingNotification = @"WebViewDidEndEditingNotification"; 471NSString * const WebViewDidChangeTypingStyleNotification = @"WebViewDidChangeTypingStyleNotification"; 472NSString * const WebViewDidChangeSelectionNotification = @"WebViewDidChangeSelectionNotification"; 473 474enum { WebViewVersion = 4 }; 475 476#define timedLayoutSize 4096 477 478static NSMutableSet *schemesWithRepresentationsSet; 479 480NSString *_WebCanGoBackKey = @"canGoBack"; 481NSString *_WebCanGoForwardKey = @"canGoForward"; 482NSString *_WebEstimatedProgressKey = @"estimatedProgress"; 483NSString *_WebIsLoadingKey = @"isLoading"; 484NSString *_WebMainFrameIconKey = @"mainFrameIcon"; 485NSString *_WebMainFrameTitleKey = @"mainFrameTitle"; 486NSString *_WebMainFrameURLKey = @"mainFrameURL"; 487NSString *_WebMainFrameDocumentKey = @"mainFrameDocument"; 488 489NSString *_WebViewDidStartAcceleratedCompositingNotification = @"_WebViewDidStartAcceleratedCompositing"; 490 491NSString *WebKitKerningAndLigaturesEnabledByDefaultDefaultsKey = @"WebKitKerningAndLigaturesEnabledByDefault"; 492 493@interface WebProgressItem : NSObject 494{ 495@public 496 long long bytesReceived; 497 long long estimatedLength; 498} 499@end 500 501@implementation WebProgressItem 502@end 503 504static BOOL continuousSpellCheckingEnabled; 505static BOOL grammarCheckingEnabled; 506static BOOL automaticQuoteSubstitutionEnabled; 507static BOOL automaticLinkDetectionEnabled; 508static BOOL automaticDashSubstitutionEnabled; 509static BOOL automaticTextReplacementEnabled; 510static BOOL automaticSpellingCorrectionEnabled; 511 512@implementation WebView (AllWebViews) 513 514static CFSetCallBacks NonRetainingSetCallbacks = { 515 0, 516 NULL, 517 NULL, 518 CFCopyDescription, 519 CFEqual, 520 CFHash 521}; 522 523static CFMutableSetRef allWebViewsSet; 524 525+ (void)_makeAllWebViewsPerformSelector:(SEL)selector 526{ 527 if (!allWebViewsSet) 528 return; 529 530 [(NSMutableSet *)allWebViewsSet makeObjectsPerformSelector:selector]; 531} 532 533- (void)_removeFromAllWebViewsSet 534{ 535 if (allWebViewsSet) 536 CFSetRemoveValue(allWebViewsSet, self); 537} 538 539- (void)_addToAllWebViewsSet 540{ 541 if (!allWebViewsSet) 542 allWebViewsSet = CFSetCreateMutable(NULL, 0, &NonRetainingSetCallbacks); 543 544 CFSetSetValue(allWebViewsSet, self); 545} 546 547@end 548 549@implementation WebView (WebPrivate) 550 551static NSString *systemMarketingVersionForUserAgentString() 552{ 553 // Use underscores instead of dots because when we first added the Mac OS X version to the user agent string 554 // we were concerned about old DHTML libraries interpreting "4." as Netscape 4. That's no longer a concern for us 555 // but we're sticking with the underscores for compatibility with the format used by older versions of Safari. 556 return [systemMarketingVersion() stringByReplacingOccurrencesOfString:@"." withString:@"_"]; 557} 558 559static NSString *createUserVisibleWebKitVersionString() 560{ 561 // If the version is 4 digits long or longer, then the first digit represents 562 // the version of the OS. Our user agent string should not include this first digit, 563 // so strip it off and report the rest as the version. <rdar://problem/4997547> 564 NSString *fullVersion = [[NSBundle bundleForClass:[WebView class]] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey]; 565 NSRange nonDigitRange = [fullVersion rangeOfCharacterFromSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]]; 566 if (nonDigitRange.location == NSNotFound && [fullVersion length] >= 4) 567 return [[fullVersion substringFromIndex:1] copy]; 568 if (nonDigitRange.location != NSNotFound && nonDigitRange.location >= 4) 569 return [[fullVersion substringFromIndex:1] copy]; 570 return [fullVersion copy]; 571} 572 573+ (NSString *)_standardUserAgentWithApplicationName:(NSString *)applicationName 574{ 575 // Note: Do *not* move the initialization of osVersion nor webKitVersion into the declaration. 576 // Garbage collection won't correctly mark the global variable in that case <rdar://problem/5733674>. 577 static NSString *osVersion; 578 static NSString *webKitVersion; 579 if (!osVersion) 580 osVersion = [systemMarketingVersionForUserAgentString() retain]; 581 if (!webKitVersion) 582 webKitVersion = createUserVisibleWebKitVersionString(); 583 if ([applicationName length]) 584 return [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; " PROCESSOR " Mac OS X %@) AppleWebKit/%@ (KHTML, like Gecko) %@", osVersion, webKitVersion, applicationName]; 585 return [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; " PROCESSOR " Mac OS X %@) AppleWebKit/%@ (KHTML, like Gecko)", osVersion, webKitVersion]; 586} 587 588+ (void)_reportException:(JSValueRef)exception inContext:(JSContextRef)context 589{ 590 if (!exception || !context) 591 return; 592 593 JSC::ExecState* execState = toJS(context); 594 JSLockHolder lock(execState); 595 596 // Make sure the context has a DOMWindow global object, otherwise this context didn't originate from a WebView. 597 if (!toJSDOMWindow(execState->lexicalGlobalObject())) 598 return; 599 600 reportException(execState, toJS(execState, exception)); 601} 602 603static void WebKitInitializeApplicationCachePathIfNecessary() 604{ 605 static BOOL initialized = NO; 606 if (initialized) 607 return; 608 609 NSString *appName = [[NSBundle mainBundle] bundleIdentifier]; 610 if (!appName) 611 appName = [[NSProcessInfo processInfo] processName]; 612 613 ASSERT(appName); 614 615 NSString* cacheDir = [NSString _webkit_localCacheDirectoryWithBundleIdentifier:appName]; 616 617 cacheStorage().setCacheDirectory(cacheDir); 618 initialized = YES; 619} 620 621static bool shouldEnableLoadDeferring() 622{ 623 return !applicationIsAdobeInstaller(); 624} 625 626static bool shouldRestrictWindowFocus() 627{ 628 return !applicationIsHRBlock(); 629} 630 631- (void)_dispatchPendingLoadRequests 632{ 633 resourceLoadScheduler()->servePendingRequests(); 634} 635 636- (void)_registerDraggedTypes 637{ 638 NSArray *editableTypes = [WebHTMLView _insertablePasteboardTypes]; 639 NSArray *URLTypes = [NSPasteboard _web_dragTypesForURL]; 640 NSMutableSet *types = [[NSMutableSet alloc] initWithArray:editableTypes]; 641 [types addObjectsFromArray:URLTypes]; 642 [self registerForDraggedTypes:[types allObjects]]; 643 [types release]; 644} 645 646#if __MAC_OS_X_VERSION_MIN_REQUIRED == 1060 647// This method should be removed once we no longer want to keep Safari 5.0.x working with nightly builds. 648- (BOOL)_usesDocumentViews 649{ 650 return true; 651} 652#endif 653 654static bool needsOutlookQuirksScript() 655{ 656 static bool isOutlookNeedingQuirksScript = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_HTML5_PARSER) 657 && applicationIsMicrosoftOutlook(); 658 return isOutlookNeedingQuirksScript; 659} 660 661static NSString *leakOutlookQuirksUserScriptContents() 662{ 663 NSString *scriptPath = [[NSBundle bundleForClass:[WebView class]] pathForResource:@"OutlookQuirksUserScript" ofType:@"js"]; 664 NSStringEncoding encoding; 665 return [[NSString alloc] initWithContentsOfFile:scriptPath usedEncoding:&encoding error:0]; 666} 667 668-(void)_injectOutlookQuirksScript 669{ 670 static NSString *outlookQuirksScriptContents = leakOutlookQuirksUserScriptContents(); 671 core(self)->group().addUserScriptToWorld(core([WebScriptWorld world]), 672 outlookQuirksScriptContents, KURL(), Vector<String>(), Vector<String>(), InjectAtDocumentEnd, InjectInAllFrames); 673} 674 675static bool shouldRespectPriorityInCSSAttributeSetters() 676{ 677 static bool isIAdProducerNeedingAttributeSetterQuirk = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_CSS_ATTRIBUTE_SETTERS_IGNORING_PRIORITY) 678 && [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.iAdProducer"]; 679 return isIAdProducerNeedingAttributeSetterQuirk; 680} 681 682static bool shouldUseLegacyBackgroundSizeShorthandBehavior() 683{ 684 static bool shouldUseLegacyBackgroundSizeShorthandBehavior = applicationIsVersions() 685 && !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_LEGACY_BACKGROUNDSIZE_SHORTHAND_BEHAVIOR); 686 return shouldUseLegacyBackgroundSizeShorthandBehavior; 687} 688 689- (void)_commonInitializationWithFrameName:(NSString *)frameName groupName:(NSString *)groupName 690{ 691 WebCoreThreadViolationCheckRoundTwo(); 692 693#ifndef NDEBUG 694 WTF::RefCountedLeakCounter::suppressMessages(webViewIsOpen); 695#endif 696 697 WebPreferences *standardPreferences = [WebPreferences standardPreferences]; 698 [standardPreferences willAddToWebView]; 699 700 _private->preferences = [standardPreferences retain]; 701 _private->mainFrameDocumentReady = NO; 702 _private->drawsBackground = YES; 703 _private->backgroundColor = [[NSColor colorWithDeviceWhite:1 alpha:1] retain]; 704 _private->includesFlattenedCompositingLayersWhenDrawingToBitmap = YES; 705 706 NSRect f = [self frame]; 707 WebFrameView *frameView = [[WebFrameView alloc] initWithFrame: NSMakeRect(0,0,f.size.width,f.size.height)]; 708 [frameView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; 709 [self addSubview:frameView]; 710 [frameView release]; 711 712 static bool didOneTimeInitialization = false; 713 if (!didOneTimeInitialization) { 714#if !LOG_DISABLED 715 WebKitInitializeLoggingChannelsIfNecessary(); 716 WebCore::initializeLoggingChannelsIfNecessary(); 717#endif // !LOG_DISABLED 718 719 // Initialize our platform strategies first before invoking the rest 720 // of the initialization code which may depend on the strategies. 721 WebPlatformStrategies::initializeIfNecessary(); 722 723#if ENABLE(SQL_DATABASE) 724 [WebDatabaseManager sharedWebDatabaseManager]; 725#endif 726 727 WebKitInitializeStorageIfNecessary(); 728 WebKitInitializeApplicationCachePathIfNecessary(); 729 730 Settings::setDefaultMinDOMTimerInterval(0.004); 731 732 Settings::setShouldRespectPriorityInCSSAttributeSetters(shouldRespectPriorityInCSSAttributeSetters()); 733 734 didOneTimeInitialization = true; 735 } 736 737 Page::PageClients pageClients; 738 pageClients.chromeClient = new WebChromeClient(self); 739 pageClients.contextMenuClient = new WebContextMenuClient(self); 740 pageClients.editorClient = new WebEditorClient(self); 741#if ENABLE(DRAG_SUPPORT) 742 pageClients.dragClient = new WebDragClient(self); 743#endif 744 pageClients.inspectorClient = new WebInspectorClient(self); 745 pageClients.alternativeTextClient = new WebAlternativeTextClient(self); 746 _private->page = new Page(pageClients); 747#if ENABLE(GEOLOCATION) 748 WebCore::provideGeolocationTo(_private->page, new WebGeolocationClient(self)); 749#endif 750#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS) 751 WebCore::provideNotification(_private->page, new WebNotificationClient(self)); 752#endif 753#if ENABLE(DEVICE_ORIENTATION) 754 WebCore::provideDeviceOrientationTo(_private->page, new WebDeviceOrientationClient(self)); 755#endif 756 757 _private->page->setCanStartMedia([self window]); 758 _private->page->settings()->setLocalStorageDatabasePath([[self preferences] _localStorageDatabasePath]); 759 _private->page->settings()->setUseLegacyBackgroundSizeShorthandBehavior(shouldUseLegacyBackgroundSizeShorthandBehavior()); 760 761 if (needsOutlookQuirksScript()) { 762 _private->page->settings()->setShouldInjectUserScriptsInInitialEmptyDocument(true); 763 [self _injectOutlookQuirksScript]; 764 } 765 766 if ([[NSUserDefaults standardUserDefaults] objectForKey:WebSmartInsertDeleteEnabled]) 767 [self setSmartInsertDeleteEnabled:[[NSUserDefaults standardUserDefaults] boolForKey:WebSmartInsertDeleteEnabled]]; 768 769 [WebFrame _createMainFrameWithPage:_private->page frameName:frameName frameView:frameView]; 770 771 NSRunLoop *runLoop = [NSRunLoop mainRunLoop]; 772 773 if (WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_LOADING_DURING_COMMON_RUNLOOP_MODES)) 774 [self scheduleInRunLoop:runLoop forMode:(NSString *)kCFRunLoopCommonModes]; 775 else 776 [self scheduleInRunLoop:runLoop forMode:NSDefaultRunLoopMode]; 777 778 [self _addToAllWebViewsSet]; 779 [self setGroupName:groupName]; 780 781 // If there's already a next key view (e.g., from a nib), wire it up to our 782 // contained frame view. In any case, wire our next key view up to the our 783 // contained frame view. This works together with our becomeFirstResponder 784 // and setNextKeyView overrides. 785 NSView *nextKeyView = [self nextKeyView]; 786 if (nextKeyView && nextKeyView != frameView) 787 [frameView setNextKeyView:nextKeyView]; 788 [super setNextKeyView:frameView]; 789 790 if ([[self class] shouldIncludeInWebKitStatistics]) 791 ++WebViewCount; 792 793 [self _registerDraggedTypes]; 794 795 [self _setVisibilityState:([self _isViewVisible] ? WebPageVisibilityStateVisible : WebPageVisibilityStateHidden) isInitialState:YES]; 796 797 WebPreferences *prefs = [self preferences]; 798 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:) 799 name:WebPreferencesChangedInternalNotification object:prefs]; 800 801 [self _preferencesChanged:[self preferences]]; 802 [[self preferences] _postPreferencesChangedAPINotification]; 803 804 memoryPressureHandler().install(); 805 806 if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_LOCAL_RESOURCE_SECURITY_RESTRICTION)) { 807 // Originally, we allowed all local loads. 808 SecurityPolicy::setLocalLoadPolicy(SecurityPolicy::AllowLocalLoadsForAll); 809 } else if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_MORE_STRICT_LOCAL_RESOURCE_SECURITY_RESTRICTION)) { 810 // Later, we allowed local loads for local URLs and documents loaded 811 // with substitute data. 812 SecurityPolicy::setLocalLoadPolicy(SecurityPolicy::AllowLocalLoadsForLocalAndSubstituteData); 813 } 814 815 if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_CONTENT_SNIFFING_FOR_FILE_URLS)) 816 ResourceHandle::forceContentSniffing(); 817 818#if USE(GLIB) 819 [self _scheduleGlibContextIterations]; 820#endif 821} 822 823- (id)_initWithFrame:(NSRect)f frameName:(NSString *)frameName groupName:(NSString *)groupName usesDocumentViews:(BOOL)usesDocumentViews 824{ 825 // FIXME: Remove the usesDocumentViews parameter; it's only here for compatibility with WebKit nightly builds 826 // running against Safari 5 on Leopard. 827 ASSERT(usesDocumentViews); 828 829 self = [super initWithFrame:f]; 830 if (!self) 831 return nil; 832 833#ifdef ENABLE_WEBKIT_UNSET_DYLD_FRAMEWORK_PATH 834 // DYLD_FRAMEWORK_PATH is used so Safari will load the development version of WebKit, which 835 // may not work with other WebKit applications. Unsetting DYLD_FRAMEWORK_PATH removes the 836 // need for Safari to unset it to prevent it from being passed to applications it launches. 837 // Unsetting it when a WebView is first created is as good a place as any. 838 // See <http://bugs.webkit.org/show_bug.cgi?id=4286> for more details. 839 if (getenv("WEBKIT_UNSET_DYLD_FRAMEWORK_PATH")) { 840 unsetenv("DYLD_FRAMEWORK_PATH"); 841 unsetenv("WEBKIT_UNSET_DYLD_FRAMEWORK_PATH"); 842 } 843#endif 844 845 _private = [[WebViewPrivate alloc] init]; 846 [self _commonInitializationWithFrameName:frameName groupName:groupName]; 847 [self setMaintainsBackForwardList: YES]; 848 _private->page->setDeviceScaleFactor([self _deviceScaleFactor]); 849 return self; 850} 851 852- (void)_viewWillDrawInternal 853{ 854 Frame* frame = [self _mainCoreFrame]; 855 if (frame && frame->view()) 856 frame->view()->updateLayoutAndStyleIfNeededRecursive(); 857} 858 859+ (NSArray *)_supportedMIMETypes 860{ 861 // Load the plug-in DB allowing plug-ins to install types. 862 [WebPluginDatabase sharedDatabase]; 863 return [[WebFrameView _viewTypesAllowImageTypeOmission:NO] allKeys]; 864} 865 866+ (NSArray *)_supportedFileExtensions 867{ 868 NSMutableSet *extensions = [[NSMutableSet alloc] init]; 869 NSArray *MIMETypes = [self _supportedMIMETypes]; 870 NSEnumerator *enumerator = [MIMETypes objectEnumerator]; 871 NSString *MIMEType; 872 while ((MIMEType = [enumerator nextObject]) != nil) { 873 NSArray *extensionsForType = WKGetExtensionsForMIMEType(MIMEType); 874 if (extensionsForType) { 875 [extensions addObjectsFromArray:extensionsForType]; 876 } 877 } 878 NSArray *uniqueExtensions = [extensions allObjects]; 879 [extensions release]; 880 return uniqueExtensions; 881} 882 883static NSMutableSet *knownPluginMIMETypes() 884{ 885 static NSMutableSet *mimeTypes = [[NSMutableSet alloc] init]; 886 887 return mimeTypes; 888} 889 890+ (void)_registerPluginMIMEType:(NSString *)MIMEType 891{ 892 [WebView registerViewClass:[WebHTMLView class] representationClass:[WebHTMLRepresentation class] forMIMEType:MIMEType]; 893 [knownPluginMIMETypes() addObject:MIMEType]; 894} 895 896+ (void)_unregisterPluginMIMEType:(NSString *)MIMEType 897{ 898 [self _unregisterViewClassAndRepresentationClassForMIMEType:MIMEType]; 899 [knownPluginMIMETypes() removeObject:MIMEType]; 900} 901 902+ (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType allowingPlugins:(BOOL)allowPlugins 903{ 904 MIMEType = [MIMEType lowercaseString]; 905 Class viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:YES] _webkit_objectForMIMEType:MIMEType]; 906 Class repClass = [[WebDataSource _repTypesAllowImageTypeOmission:YES] _webkit_objectForMIMEType:MIMEType]; 907 908 if (!viewClass || !repClass || [[WebPDFView supportedMIMETypes] containsObject:MIMEType]) { 909 // Our optimization to avoid loading the plug-in DB and image types for the HTML case failed. 910 911 if (allowPlugins) { 912 // Load the plug-in DB allowing plug-ins to install types. 913 [WebPluginDatabase sharedDatabase]; 914 } 915 916 // Load the image types and get the view class and rep class. This should be the fullest picture of all handled types. 917 viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:NO] _webkit_objectForMIMEType:MIMEType]; 918 repClass = [[WebDataSource _repTypesAllowImageTypeOmission:NO] _webkit_objectForMIMEType:MIMEType]; 919 } 920 921 if (viewClass && repClass) { 922 if (viewClass == [WebHTMLView class] && repClass == [WebHTMLRepresentation class]) { 923 // Special-case WebHTMLView for text types that shouldn't be shown. 924 if ([[WebHTMLView unsupportedTextMIMETypes] containsObject:MIMEType]) 925 return NO; 926 927 // If the MIME type is a known plug-in we might not want to load it. 928 if (!allowPlugins && [knownPluginMIMETypes() containsObject:MIMEType]) { 929 BOOL isSupportedByWebKit = [[WebHTMLView supportedNonImageMIMETypes] containsObject:MIMEType] || 930 [[WebHTMLView supportedMIMETypes] containsObject:MIMEType]; 931 932 // If this is a known plug-in MIME type and WebKit can't show it natively, we don't want to show it. 933 if (!isSupportedByWebKit) 934 return NO; 935 } 936 } 937 if (vClass) 938 *vClass = viewClass; 939 if (rClass) 940 *rClass = repClass; 941 return YES; 942 } 943 944 return NO; 945} 946 947- (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType 948{ 949 if ([[self class] _viewClass:vClass andRepresentationClass:rClass forMIMEType:MIMEType allowingPlugins:[_private->preferences arePlugInsEnabled]]) 950 return YES; 951 952 if (_private->pluginDatabase) { 953 WebBasePluginPackage *pluginPackage = [_private->pluginDatabase pluginForMIMEType:MIMEType]; 954 if (pluginPackage) { 955 if (vClass) 956 *vClass = [WebHTMLView class]; 957 if (rClass) 958 *rClass = [WebHTMLRepresentation class]; 959 return YES; 960 } 961 } 962 963 return NO; 964} 965 966+ (void)_setAlwaysUseATSU:(BOOL)f 967{ 968 [self _setAlwaysUsesComplexTextCodePath:f]; 969} 970 971+ (void)_setAlwaysUsesComplexTextCodePath:(BOOL)f 972{ 973 Font::setCodePath(f ? Font::Complex : Font::Auto); 974} 975 976+ (void)_setAllowsRoundingHacks:(BOOL)allowsRoundingHacks 977{ 978 TextRun::setAllowsRoundingHacks(allowsRoundingHacks); 979} 980 981+ (BOOL)_allowsRoundingHacks 982{ 983 return TextRun::allowsRoundingHacks(); 984} 985 986+ (BOOL)canCloseAllWebViews 987{ 988 return DOMWindow::dispatchAllPendingBeforeUnloadEvents(); 989} 990 991+ (void)closeAllWebViews 992{ 993 DOMWindow::dispatchAllPendingUnloadEvents(); 994 995 // This will close the WebViews in a random order. Change this if close order is important. 996 // Make a new set to avoid mutating the set we are enumerating. 997 NSSet *webViewsToClose = [NSSet setWithSet:(NSSet *)allWebViewsSet]; 998 NSEnumerator *enumerator = [webViewsToClose objectEnumerator]; 999 while (WebView *webView = [enumerator nextObject]) 1000 [webView close]; 1001} 1002 1003+ (BOOL)canShowFile:(NSString *)path 1004{ 1005 return [[self class] canShowMIMEType:[WebView _MIMETypeForFile:path]]; 1006} 1007 1008+ (NSString *)suggestedFileExtensionForMIMEType:(NSString *)type 1009{ 1010 return WKGetPreferredExtensionForMIMEType(type); 1011} 1012 1013- (BOOL)_isClosed 1014{ 1015 return !_private || _private->closed; 1016} 1017 1018- (void)_closePluginDatabases 1019{ 1020 pluginDatabaseClientCount--; 1021 1022 // Close both sets of plug-in databases because plug-ins need an opportunity to clean up files, etc. 1023 1024 // Unload the WebView local plug-in database. 1025 if (_private->pluginDatabase) { 1026 [_private->pluginDatabase destroyAllPluginInstanceViews]; 1027 [_private->pluginDatabase close]; 1028 [_private->pluginDatabase release]; 1029 _private->pluginDatabase = nil; 1030 } 1031 1032 // Keep the global plug-in database active until the app terminates to avoid having to reload plug-in bundles. 1033 if (!pluginDatabaseClientCount && applicationIsTerminating) 1034 [WebPluginDatabase closeSharedDatabase]; 1035} 1036 1037- (void)_closeWithFastTeardown 1038{ 1039#ifndef NDEBUG 1040 WTF::RefCountedLeakCounter::suppressMessages("At least one WebView was closed with fast teardown."); 1041#endif 1042 1043 [[NSDistributedNotificationCenter defaultCenter] removeObserver:self]; 1044 [[NSNotificationCenter defaultCenter] removeObserver:self]; 1045 1046 [self _closePluginDatabases]; 1047} 1048 1049static bool fastDocumentTeardownEnabled() 1050{ 1051#ifdef NDEBUG 1052 static bool enabled = ![[NSUserDefaults standardUserDefaults] boolForKey:WebKitEnableFullDocumentTeardownPreferenceKey]; 1053#else 1054 static bool initialized = false; 1055 static bool enabled = false; 1056 if (!initialized) { 1057 // This allows debug builds to default to not have fast teardown, so leak checking still works. 1058 // But still allow the WebKitEnableFullDocumentTeardown default to override it if present. 1059 NSNumber *setting = [[NSUserDefaults standardUserDefaults] objectForKey:WebKitEnableFullDocumentTeardownPreferenceKey]; 1060 if (setting) 1061 enabled = ![setting boolValue]; 1062 initialized = true; 1063 } 1064#endif 1065 return enabled; 1066} 1067 1068// _close is here only for backward compatibility; clients and subclasses should use 1069// public method -close instead. 1070- (void)_close 1071{ 1072 if (!_private || _private->closed) 1073 return; 1074 1075 _private->closed = YES; 1076 [self _removeFromAllWebViewsSet]; 1077 1078#ifndef NDEBUG 1079 WTF::RefCountedLeakCounter::cancelMessageSuppression(webViewIsOpen); 1080#endif 1081 1082 // To quit the apps fast we skip document teardown, except plugins 1083 // need to be destroyed and unloaded. 1084 if (applicationIsTerminating && fastDocumentTeardownEnabled()) { 1085 [self _closeWithFastTeardown]; 1086 return; 1087 } 1088 1089#if ENABLE(VIDEO) 1090 [self _exitFullscreen]; 1091#endif 1092 1093 if (Frame* mainFrame = [self _mainCoreFrame]) 1094 mainFrame->loader()->detachFromParent(); 1095 1096 [self setHostWindow:nil]; 1097 1098 [self setDownloadDelegate:nil]; 1099 [self setEditingDelegate:nil]; 1100 [self setFrameLoadDelegate:nil]; 1101 [self setPolicyDelegate:nil]; 1102 [self setResourceLoadDelegate:nil]; 1103 [self setScriptDebugDelegate:nil]; 1104 [self setUIDelegate:nil]; 1105 1106 [_private->inspector webViewClosed]; 1107 1108 // To avoid leaks, call removeDragCaret in case it wasn't called after moveDragCaretToPoint. 1109 [self removeDragCaret]; 1110 1111 // Deleteing the WebCore::Page will clear the page cache so we call destroy on 1112 // all the plug-ins in the page cache to break any retain cycles. 1113 // See comment in HistoryItem::releaseAllPendingPageCaches() for more information. 1114 Page* page = _private->page; 1115 _private->page = 0; 1116 delete page; 1117 1118 if (_private->hasSpellCheckerDocumentTag) { 1119 [[NSSpellChecker sharedSpellChecker] closeSpellDocumentWithTag:_private->spellCheckerDocumentTag]; 1120 _private->hasSpellCheckerDocumentTag = NO; 1121 } 1122 1123#if USE(ACCELERATED_COMPOSITING) 1124 if (_private->layerFlushController) { 1125 _private->layerFlushController->invalidateObserver(); 1126 _private->layerFlushController = nullptr; 1127 } 1128#endif 1129 1130#if USE(GLIB) 1131 [self _clearGlibLoopObserver]; 1132#endif 1133 1134 [[self _notificationProvider] unregisterWebView:self]; 1135 1136 [[NSDistributedNotificationCenter defaultCenter] removeObserver:self]; 1137 [[NSNotificationCenter defaultCenter] removeObserver:self]; 1138 1139 [WebPreferences _removeReferenceForIdentifier:[self preferencesIdentifier]]; 1140 1141 WebPreferences *preferences = _private->preferences; 1142 _private->preferences = nil; 1143 [preferences didRemoveFromWebView]; 1144 [preferences release]; 1145 1146 [self _closePluginDatabases]; 1147 1148#ifndef NDEBUG 1149 // Need this to make leak messages accurate. 1150 if (applicationIsTerminating) { 1151 gcController().garbageCollectNow(); 1152 [WebCache setDisabled:YES]; 1153 } 1154#endif 1155} 1156 1157// Indicates if the WebView is in the midst of a user gesture. 1158- (BOOL)_isProcessingUserGesture 1159{ 1160 return ScriptController::processingUserGesture(); 1161} 1162 1163+ (NSString *)_MIMETypeForFile:(NSString *)path 1164{ 1165 NSString *extension = [path pathExtension]; 1166 NSString *MIMEType = nil; 1167 1168 // Get the MIME type from the extension. 1169 if ([extension length] != 0) { 1170 MIMEType = WKGetMIMETypeForExtension(extension); 1171 } 1172 1173 // If we can't get a known MIME type from the extension, sniff. 1174 if ([MIMEType length] == 0 || [MIMEType isEqualToString:@"application/octet-stream"]) { 1175 NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:path]; 1176 NSData *data = [handle readDataOfLength:WEB_GUESS_MIME_TYPE_PEEK_LENGTH]; 1177 [handle closeFile]; 1178 if ([data length] != 0) { 1179 MIMEType = [data _webkit_guessedMIMEType]; 1180 } 1181 if ([MIMEType length] == 0) { 1182 MIMEType = @"application/octet-stream"; 1183 } 1184 } 1185 1186 return MIMEType; 1187} 1188 1189- (WebDownload *)_downloadURL:(NSURL *)URL 1190{ 1191 ASSERT(URL); 1192 1193 NSURLRequest *request = [[NSURLRequest alloc] initWithURL:URL]; 1194 WebDownload *download = [WebDownload _downloadWithRequest:request 1195 delegate:_private->downloadDelegate 1196 directory:nil]; 1197 [request release]; 1198 1199 return download; 1200} 1201 1202- (WebView *)_openNewWindowWithRequest:(NSURLRequest *)request 1203{ 1204 NSDictionary *features = [[NSDictionary alloc] init]; 1205 WebView *newWindowWebView = [[self _UIDelegateForwarder] webView:self 1206 createWebViewWithRequest:nil 1207 windowFeatures:features]; 1208 [features release]; 1209 if (!newWindowWebView) 1210 return nil; 1211 1212 CallUIDelegate(newWindowWebView, @selector(webViewShow:)); 1213 return newWindowWebView; 1214} 1215 1216- (WebInspector *)inspector 1217{ 1218 if (!_private->inspector) 1219 _private->inspector = [[WebInspector alloc] initWithWebView:self]; 1220 return _private->inspector; 1221} 1222 1223- (WebCore::Page*)page 1224{ 1225 return _private->page; 1226} 1227 1228- (NSMenu *)_menuForElement:(NSDictionary *)element defaultItems:(NSArray *)items 1229{ 1230 NSArray *defaultMenuItems = [[WebDefaultUIDelegate sharedUIDelegate] webView:self contextMenuItemsForElement:element defaultMenuItems:items]; 1231 NSArray *menuItems = defaultMenuItems; 1232 1233 // CallUIDelegate returns nil if UIDelegate is nil or doesn't respond to the selector. So we need to check that here 1234 // to distinguish between using defaultMenuItems or the delegate really returning nil to say "no context menu". 1235 SEL selector = @selector(webView:contextMenuItemsForElement:defaultMenuItems:); 1236 if (_private->UIDelegate && [_private->UIDelegate respondsToSelector:selector]) { 1237 menuItems = CallUIDelegate(self, selector, element, defaultMenuItems); 1238 if (!menuItems) 1239 return nil; 1240 } 1241 1242 unsigned count = [menuItems count]; 1243 if (!count) 1244 return nil; 1245 1246 NSMenu *menu = [[NSMenu alloc] init]; 1247 for (unsigned i = 0; i < count; i++) 1248 [menu addItem:[menuItems objectAtIndex:i]]; 1249 1250 return [menu autorelease]; 1251} 1252 1253- (void)_mouseDidMoveOverElement:(NSDictionary *)dictionary modifierFlags:(NSUInteger)modifierFlags 1254{ 1255 // We originally intended to call this delegate method sometimes with a nil dictionary, but due to 1256 // a bug dating back to WebKit 1.0 this delegate was never called with nil! Unfortunately we can't 1257 // start calling this with nil since it will break Adobe Help Viewer, and possibly other clients. 1258 if (!dictionary) 1259 return; 1260 CallUIDelegate(self, @selector(webView:mouseDidMoveOverElement:modifierFlags:), dictionary, modifierFlags); 1261} 1262 1263- (void)_loadBackForwardListFromOtherView:(WebView *)otherView 1264{ 1265 if (!_private->page) 1266 return; 1267 1268 if (!otherView->_private->page) 1269 return; 1270 1271 // It turns out the right combination of behavior is done with the back/forward load 1272 // type. (See behavior matrix at the top of WebFramePrivate.) So we copy all the items 1273 // in the back forward list, and go to the current one. 1274 1275 BackForwardList* backForwardList = _private->page->backForwardList(); 1276 ASSERT(!backForwardList->currentItem()); // destination list should be empty 1277 1278 BackForwardList* otherBackForwardList = otherView->_private->page->backForwardList(); 1279 if (!otherBackForwardList->currentItem()) 1280 return; // empty back forward list, bail 1281 1282 HistoryItem* newItemToGoTo = 0; 1283 1284 int lastItemIndex = otherBackForwardList->forwardListCount(); 1285 for (int i = -otherBackForwardList->backListCount(); i <= lastItemIndex; ++i) { 1286 if (i == 0) { 1287 // If this item is showing , save away its current scroll and form state, 1288 // since that might have changed since loading and it is normally not saved 1289 // until we leave that page. 1290 otherView->_private->page->mainFrame()->loader()->history()->saveDocumentAndScrollState(); 1291 } 1292 RefPtr<HistoryItem> newItem = otherBackForwardList->itemAtIndex(i)->copy(); 1293 if (i == 0) 1294 newItemToGoTo = newItem.get(); 1295 backForwardList->addItem(newItem.release()); 1296 } 1297 1298 ASSERT(newItemToGoTo); 1299 _private->page->goToItem(newItemToGoTo, FrameLoadTypeIndexedBackForward); 1300} 1301 1302- (void)_setFormDelegate: (id<WebFormDelegate>)delegate 1303{ 1304 _private->formDelegate = delegate; 1305} 1306 1307- (id<WebFormDelegate>)_formDelegate 1308{ 1309 return _private->formDelegate; 1310} 1311 1312- (BOOL)_needsAdobeFrameReloadingQuirk 1313{ 1314 static BOOL needsQuirk = WKAppVersionCheckLessThan(@"com.adobe.Acrobat", -1, 9.0) 1315 || WKAppVersionCheckLessThan(@"com.adobe.Acrobat.Pro", -1, 9.0) 1316 || WKAppVersionCheckLessThan(@"com.adobe.Reader", -1, 9.0) 1317 || WKAppVersionCheckLessThan(@"com.adobe.distiller", -1, 9.0) 1318 || WKAppVersionCheckLessThan(@"com.adobe.Contribute", -1, 4.2) 1319 || WKAppVersionCheckLessThan(@"com.adobe.dreamweaver-9.0", -1, 9.1) 1320 || WKAppVersionCheckLessThan(@"com.macromedia.fireworks", -1, 9.1) 1321 || WKAppVersionCheckLessThan(@"com.adobe.InCopy", -1, 5.1) 1322 || WKAppVersionCheckLessThan(@"com.adobe.InDesign", -1, 5.1) 1323 || WKAppVersionCheckLessThan(@"com.adobe.Soundbooth", -1, 2); 1324 1325 return needsQuirk; 1326} 1327 1328- (BOOL)_needsLinkElementTextCSSQuirk 1329{ 1330 static BOOL needsQuirk = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_LINK_ELEMENT_TEXT_CSS_QUIRK) 1331 && WKAppVersionCheckLessThan(@"com.e-frontier.shade10", -1, 10.6); 1332 return needsQuirk; 1333} 1334 1335- (BOOL)_needsIsLoadingInAPISenseQuirk 1336{ 1337 static BOOL needsQuirk = WKAppVersionCheckLessThan(@"com.apple.iAdProducer", -1, 2.1); 1338 1339 return needsQuirk; 1340} 1341 1342- (BOOL)_needsKeyboardEventDisambiguationQuirks 1343{ 1344 static BOOL needsQuirks = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_IE_COMPATIBLE_KEYBOARD_EVENT_DISPATCH) && !applicationIsSafari(); 1345 return needsQuirks; 1346} 1347 1348- (BOOL)_needsFrameLoadDelegateRetainQuirk 1349{ 1350 static BOOL needsQuirk = WKAppVersionCheckLessThan(@"com.equinux.iSale5", -1, 5.6); 1351 return needsQuirk; 1352} 1353 1354static bool needsDidFinishLoadOrderQuirk() 1355{ 1356 static bool needsQuirk = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_CORRECT_DID_FINISH_LOAD_ORDER) && applicationIsAppleMail(); 1357 return needsQuirk; 1358} 1359 1360static bool needsSelfRetainWhileLoadingQuirk() 1361{ 1362 static bool needsQuirk = applicationIsAperture(); 1363 return needsQuirk; 1364} 1365 1366- (BOOL)_needsPreHTML5ParserQuirks 1367{ 1368 // AOL Instant Messenger and Microsoft My Day contain markup incompatible 1369 // with the new HTML5 parser. If these applications were linked against a 1370 // version of WebKit prior to the introduction of the HTML5 parser, enable 1371 // parser quirks to maintain compatibility. For details, see 1372 // <https://bugs.webkit.org/show_bug.cgi?id=46134> and 1373 // <https://bugs.webkit.org/show_bug.cgi?id=46334>. 1374 static bool isApplicationNeedingParserQuirks = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_HTML5_PARSER) 1375 && (applicationIsAOLInstantMessenger() || applicationIsMicrosoftMyDay()); 1376 1377 // Mail.app must continue to display HTML email that contains quirky markup. 1378 static bool isAppleMail = applicationIsAppleMail(); 1379 1380 return isApplicationNeedingParserQuirks 1381 || isAppleMail 1382#if ENABLE(DASHBOARD_SUPPORT) 1383 // Pre-HTML5 parser quirks are required to remain compatible with many 1384 // Dashboard widgets. See <rdar://problem/8175982>. 1385 || (_private->page && _private->page->settings()->usesDashboardBackwardCompatibilityMode()) 1386#endif 1387 || [[self preferences] usePreHTML5ParserQuirks]; 1388} 1389 1390- (BOOL)_needsUnrestrictedGetMatchedCSSRules 1391{ 1392 static bool needsUnrestrictedGetMatchedCSSRules = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_GET_MATCHED_CSS_RULES_RESTRICTIONS) && applicationIsSafari(); 1393 return needsUnrestrictedGetMatchedCSSRules; 1394} 1395 1396- (void)_preferencesChangedNotification:(NSNotification *)notification 1397{ 1398 WebPreferences *preferences = (WebPreferences *)[notification object]; 1399 [self _preferencesChanged:preferences]; 1400} 1401 1402- (void)_preferencesChanged:(WebPreferences *)preferences 1403{ 1404 ASSERT(preferences == [self preferences]); 1405 if (!_private->userAgentOverridden) 1406 _private->userAgent = String(); 1407 1408 // Cache this value so we don't have to read NSUserDefaults on each page load 1409 _private->useSiteSpecificSpoofing = [preferences _useSiteSpecificSpoofing]; 1410 1411 // Update corresponding WebCore Settings object. 1412 if (!_private->page) 1413 return; 1414 1415 Settings* settings = _private->page->settings(); 1416 1417 settings->setCursiveFontFamily([preferences cursiveFontFamily]); 1418 settings->setDefaultFixedFontSize([preferences defaultFixedFontSize]); 1419 settings->setDefaultFontSize([preferences defaultFontSize]); 1420 settings->setDefaultTextEncodingName([preferences defaultTextEncodingName]); 1421 settings->setUsesEncodingDetector([preferences usesEncodingDetector]); 1422 settings->setFantasyFontFamily([preferences fantasyFontFamily]); 1423 settings->setFixedFontFamily([preferences fixedFontFamily]); 1424 settings->setScreenFontSubstitutionEnabled( 1425#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 1426 [[NSUserDefaults standardUserDefaults] boolForKey:@"NSFontDefaultScreenFontSubstitutionEnabled"] || 1427#endif 1428 [preferences screenFontSubstitutionEnabled] 1429 ); 1430 settings->setForceFTPDirectoryListings([preferences _forceFTPDirectoryListings]); 1431 settings->setFTPDirectoryTemplatePath([preferences _ftpDirectoryTemplatePath]); 1432 settings->setLocalStorageDatabasePath([preferences _localStorageDatabasePath]); 1433 settings->setJavaEnabled([preferences isJavaEnabled]); 1434 settings->setScriptEnabled([preferences isJavaScriptEnabled]); 1435 settings->setWebSecurityEnabled([preferences isWebSecurityEnabled]); 1436 settings->setAllowUniversalAccessFromFileURLs([preferences allowUniversalAccessFromFileURLs]); 1437 settings->setAllowFileAccessFromFileURLs([preferences allowFileAccessFromFileURLs]); 1438 settings->setJavaScriptCanOpenWindowsAutomatically([preferences javaScriptCanOpenWindowsAutomatically]); 1439 settings->setMinimumFontSize([preferences minimumFontSize]); 1440 settings->setMinimumLogicalFontSize([preferences minimumLogicalFontSize]); 1441 settings->setPictographFontFamily([preferences pictographFontFamily]); 1442 settings->setPluginsEnabled([preferences arePlugInsEnabled]); 1443#if ENABLE(SQL_DATABASE) 1444 DatabaseManager::manager().setIsAvailable([preferences databasesEnabled]); 1445#endif 1446 settings->setLocalStorageEnabled([preferences localStorageEnabled]); 1447 settings->setExperimentalNotificationsEnabled([preferences experimentalNotificationsEnabled]); 1448 1449 bool privateBrowsingEnabled = [preferences privateBrowsingEnabled]; 1450#if PLATFORM(MAC) || USE(CFNETWORK) 1451 if (privateBrowsingEnabled) 1452 WebFrameNetworkingContext::ensurePrivateBrowsingSession(); 1453 else 1454 WebFrameNetworkingContext::destroyPrivateBrowsingSession(); 1455#endif 1456 settings->setPrivateBrowsingEnabled(privateBrowsingEnabled); 1457 1458 settings->setSansSerifFontFamily([preferences sansSerifFontFamily]); 1459 settings->setSerifFontFamily([preferences serifFontFamily]); 1460 settings->setStandardFontFamily([preferences standardFontFamily]); 1461 settings->setLoadsImagesAutomatically([preferences loadsImagesAutomatically]); 1462 settings->setLoadsSiteIconsIgnoringImageLoadingSetting([preferences loadsSiteIconsIgnoringImageLoadingPreference]); 1463 settings->setShouldPrintBackgrounds([preferences shouldPrintBackgrounds]); 1464 settings->setTextAreasAreResizable([preferences textAreasAreResizable]); 1465 settings->setShrinksStandaloneImagesToFit([preferences shrinksStandaloneImagesToFit]); 1466 settings->setEditableLinkBehavior(core([preferences editableLinkBehavior])); 1467 settings->setTextDirectionSubmenuInclusionBehavior(core([preferences textDirectionSubmenuInclusionBehavior])); 1468 settings->setDOMPasteAllowed([preferences isDOMPasteAllowed]); 1469 settings->setUsesPageCache([self usesPageCache]); 1470 settings->setPageCacheSupportsPlugins([preferences pageCacheSupportsPlugins]); 1471 settings->setBackForwardCacheExpirationInterval([preferences _backForwardCacheExpirationInterval]); 1472 settings->setShowsURLsInToolTips([preferences showsURLsInToolTips]); 1473 settings->setShowsToolTipOverTruncatedText([preferences showsToolTipOverTruncatedText]); 1474 settings->setDeveloperExtrasEnabled([preferences developerExtrasEnabled]); 1475 settings->setJavaScriptExperimentsEnabled([preferences javaScriptExperimentsEnabled]); 1476 settings->setAuthorAndUserStylesEnabled([preferences authorAndUserStylesEnabled]); 1477 settings->setApplicationChromeMode([preferences applicationChromeModeEnabled]); 1478 if ([preferences userStyleSheetEnabled]) { 1479 NSString* location = [[preferences userStyleSheetLocation] _web_originalDataAsString]; 1480 if ([location isEqualToString:@"apple-dashboard://stylesheet"]) 1481 location = @"file:///System/Library/PrivateFrameworks/DashboardClient.framework/Resources/widget.css"; 1482 settings->setUserStyleSheetLocation([NSURL URLWithString:(location ? location : @"")]); 1483 } else 1484 settings->setUserStyleSheetLocation([NSURL URLWithString:@""]); 1485 settings->setNeedsAdobeFrameReloadingQuirk([self _needsAdobeFrameReloadingQuirk]); 1486 settings->setTreatsAnyTextCSSLinkAsStylesheet([self _needsLinkElementTextCSSQuirk]); 1487 settings->setNeedsKeyboardEventDisambiguationQuirks([self _needsKeyboardEventDisambiguationQuirks]); 1488 settings->setNeedsSiteSpecificQuirks(_private->useSiteSpecificSpoofing); 1489 settings->setWebArchiveDebugModeEnabled([preferences webArchiveDebugModeEnabled]); 1490 settings->setLocalFileContentSniffingEnabled([preferences localFileContentSniffingEnabled]); 1491 settings->setOfflineWebApplicationCacheEnabled([preferences offlineWebApplicationCacheEnabled]); 1492 settings->setJavaScriptCanAccessClipboard([preferences javaScriptCanAccessClipboard]); 1493 settings->setXSSAuditorEnabled([preferences isXSSAuditorEnabled]); 1494 settings->setEnforceCSSMIMETypeInNoQuirksMode(!WKAppVersionCheckLessThan(@"com.apple.iWeb", -1, 2.1)); 1495 settings->setDNSPrefetchingEnabled([preferences isDNSPrefetchingEnabled]); 1496 1497 // FIXME: Enabling accelerated compositing when WebGL is enabled causes tests to fail on Leopard which expect HW compositing to be disabled. 1498 // Until we fix that, I will comment out the test (CFM) 1499 settings->setAcceleratedCompositingEnabled([preferences acceleratedCompositingEnabled]); 1500 settings->setAcceleratedDrawingEnabled([preferences acceleratedDrawingEnabled]); 1501 settings->setCanvasUsesAcceleratedDrawing([preferences canvasUsesAcceleratedDrawing]); 1502 settings->setShowDebugBorders([preferences showDebugBorders]); 1503 settings->setShowRepaintCounter([preferences showRepaintCounter]); 1504 settings->setWebGLEnabled([preferences webGLEnabled]); 1505 settings->setAccelerated2dCanvasEnabled([preferences accelerated2dCanvasEnabled]); 1506 settings->setLoadDeferringEnabled(shouldEnableLoadDeferring()); 1507 settings->setWindowFocusRestricted(shouldRestrictWindowFocus()); 1508 settings->setFrameFlatteningEnabled([preferences isFrameFlatteningEnabled]); 1509 settings->setSpatialNavigationEnabled([preferences isSpatialNavigationEnabled]); 1510 settings->setPaginateDuringLayoutEnabled([preferences paginateDuringLayoutEnabled]); 1511#if ENABLE(CSS_SHADERS) 1512 settings->setCSSCustomFilterEnabled([preferences cssCustomFilterEnabled]); 1513#endif 1514 RuntimeEnabledFeatures::setCSSRegionsEnabled([preferences cssRegionsEnabled]); 1515 RuntimeEnabledFeatures::setCSSCompositingEnabled([preferences cssCompositingEnabled]); 1516#if ENABLE(WEB_AUDIO) 1517 settings->setWebAudioEnabled([preferences webAudioEnabled]); 1518#endif 1519#if ENABLE(IFRAME_SEAMLESS) 1520 RuntimeEnabledFeatures::setSeamlessIFramesEnabled([preferences seamlessIFramesEnabled]); 1521#endif 1522 settings->setCSSGridLayoutEnabled([preferences cssGridLayoutEnabled]); 1523#if ENABLE(FULLSCREEN_API) 1524 settings->setFullScreenEnabled([preferences fullScreenEnabled]); 1525#endif 1526 settings->setAsynchronousSpellCheckingEnabled([preferences asynchronousSpellCheckingEnabled]); 1527 settings->setHyperlinkAuditingEnabled([preferences hyperlinkAuditingEnabled]); 1528 settings->setUsePreHTML5ParserQuirks([self _needsPreHTML5ParserQuirks]); 1529 settings->setCrossOriginCheckInGetMatchedCSSRulesDisabled([self _needsUnrestrictedGetMatchedCSSRules]); 1530 settings->setInteractiveFormValidationEnabled([self interactiveFormValidationEnabled]); 1531 settings->setValidationMessageTimerMagnification([self validationMessageTimerMagnification]); 1532#if USE(AVFOUNDATION) 1533 settings->setAVFoundationEnabled([preferences isAVFoundationEnabled]); 1534#endif 1535#if PLATFORM(MAC) 1536 settings->setQTKitEnabled([preferences isQTKitEnabled]); 1537#endif 1538 settings->setMediaPlaybackRequiresUserGesture([preferences mediaPlaybackRequiresUserGesture]); 1539 settings->setMediaPlaybackAllowsInline([preferences mediaPlaybackAllowsInline]); 1540 settings->setSuppressesIncrementalRendering([preferences suppressesIncrementalRendering]); 1541 settings->setRegionBasedColumnsEnabled([preferences regionBasedColumnsEnabled]); 1542 settings->setBackspaceKeyNavigationEnabled([preferences backspaceKeyNavigationEnabled]); 1543 settings->setWantsBalancedSetDefersLoadingBehavior([preferences wantsBalancedSetDefersLoadingBehavior]); 1544 settings->setMockScrollbarsEnabled([preferences mockScrollbarsEnabled]); 1545 1546#if ENABLE(VIDEO_TRACK) 1547 settings->setShouldDisplaySubtitles([preferences shouldDisplaySubtitles]); 1548 settings->setShouldDisplayCaptions([preferences shouldDisplayCaptions]); 1549 settings->setShouldDisplayTextDescriptions([preferences shouldDisplayTextDescriptions]); 1550#endif 1551 1552 settings->setShouldRespectImageOrientation([preferences shouldRespectImageOrientation]); 1553 settings->setNeedsIsLoadingInAPISenseQuirk([self _needsIsLoadingInAPISenseQuirk]); 1554 settings->setRequestAnimationFrameEnabled([preferences requestAnimationFrameEnabled]); 1555 settings->setNeedsDidFinishLoadOrderQuirk(needsDidFinishLoadOrderQuirk()); 1556 settings->setDiagnosticLoggingEnabled([preferences diagnosticLoggingEnabled]); 1557 settings->setLowPowerVideoAudioBufferSizeEnabled([preferences lowPowerVideoAudioBufferSizeEnabled]); 1558 1559 settings->setUseLegacyTextAlignPositionedElementBehavior([preferences useLegacyTextAlignPositionedElementBehavior]); 1560 1561 settings->setEnableInheritURIQueryComponent([preferences isInheritURIQueryComponentEnabled]); 1562 1563 switch ([preferences storageBlockingPolicy]) { 1564 case WebAllowAllStorage: 1565 settings->setStorageBlockingPolicy(SecurityOrigin::AllowAllStorage); 1566 break; 1567 case WebBlockThirdPartyStorage: 1568 settings->setStorageBlockingPolicy(SecurityOrigin::BlockThirdPartyStorage); 1569 break; 1570 case WebBlockAllStorage: 1571 settings->setStorageBlockingPolicy(SecurityOrigin::BlockAllStorage); 1572 break; 1573 } 1574 1575 settings->setPlugInSnapshottingEnabled([preferences plugInSnapshottingEnabled]); 1576 1577#if ENABLE(HIDDEN_PAGE_DOM_TIMER_THROTTLING) 1578 settings->setHiddenPageDOMTimerThrottlingEnabled([preferences hiddenPageDOMTimerThrottlingEnabled]); 1579#endif 1580#if ENABLE(PAGE_VISIBILITY_API) 1581 settings->setHiddenPageCSSAnimationSuspensionEnabled([preferences hiddenPageCSSAnimationSuspensionEnabled]); 1582#endif 1583 1584 // We have enabled this setting in WebKit2 for the sake of some ScrollingCoordinator work. 1585 // To avoid possible rendering differences, we should enable it for WebKit1 too. 1586 settings->setFixedPositionCreatesStackingContext(true); 1587 1588 NSTimeInterval timeout = [preferences incrementalRenderingSuppressionTimeoutInSeconds]; 1589 if (timeout > 0) 1590 settings->setIncrementalRenderingSuppressionTimeoutInSeconds(timeout); 1591 1592 // Application Cache Preferences are stored on the global cache storage manager, not in Settings. 1593 [WebApplicationCache setDefaultOriginQuota:[preferences applicationCacheDefaultOriginQuota]]; 1594 1595 BOOL zoomsTextOnly = [preferences zoomsTextOnly]; 1596 if (_private->zoomsTextOnly != zoomsTextOnly) 1597 [self _setZoomMultiplier:_private->zoomMultiplier isTextOnly:zoomsTextOnly]; 1598} 1599 1600static inline IMP getMethod(id o, SEL s) 1601{ 1602 return [o respondsToSelector:s] ? [o methodForSelector:s] : 0; 1603} 1604 1605- (void)_cacheResourceLoadDelegateImplementations 1606{ 1607 WebResourceDelegateImplementationCache *cache = &_private->resourceLoadDelegateImplementations; 1608 id delegate = _private->resourceProgressDelegate; 1609 1610 if (!delegate) { 1611 bzero(cache, sizeof(WebResourceDelegateImplementationCache)); 1612 return; 1613 } 1614 1615 cache->didCancelAuthenticationChallengeFunc = getMethod(delegate, @selector(webView:resource:didCancelAuthenticationChallenge:fromDataSource:)); 1616 cache->didFailLoadingWithErrorFromDataSourceFunc = getMethod(delegate, @selector(webView:resource:didFailLoadingWithError:fromDataSource:)); 1617 cache->didFinishLoadingFromDataSourceFunc = getMethod(delegate, @selector(webView:resource:didFinishLoadingFromDataSource:)); 1618 cache->didLoadResourceFromMemoryCacheFunc = getMethod(delegate, @selector(webView:didLoadResourceFromMemoryCache:response:length:fromDataSource:)); 1619 cache->didReceiveAuthenticationChallengeFunc = getMethod(delegate, @selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:)); 1620#if USE(PROTECTION_SPACE_AUTH_CALLBACK) 1621 cache->canAuthenticateAgainstProtectionSpaceFunc = getMethod(delegate, @selector(webView:resource:canAuthenticateAgainstProtectionSpace:forDataSource:)); 1622#endif 1623 cache->didReceiveContentLengthFunc = getMethod(delegate, @selector(webView:resource:didReceiveContentLength:fromDataSource:)); 1624 cache->didReceiveResponseFunc = getMethod(delegate, @selector(webView:resource:didReceiveResponse:fromDataSource:)); 1625 cache->identifierForRequestFunc = getMethod(delegate, @selector(webView:identifierForInitialRequest:fromDataSource:)); 1626 cache->plugInFailedWithErrorFunc = getMethod(delegate, @selector(webView:plugInFailedWithError:dataSource:)); 1627 cache->willCacheResponseFunc = getMethod(delegate, @selector(webView:resource:willCacheResponse:fromDataSource:)); 1628 cache->willSendRequestFunc = getMethod(delegate, @selector(webView:resource:willSendRequest:redirectResponse:fromDataSource:)); 1629 cache->shouldUseCredentialStorageFunc = getMethod(delegate, @selector(webView:resource:shouldUseCredentialStorageForDataSource:)); 1630 cache->shouldPaintBrokenImageForURLFunc = getMethod(delegate, @selector(webView:shouldPaintBrokenImageForURL:)); 1631} 1632 1633- (void)_cacheFrameLoadDelegateImplementations 1634{ 1635 WebFrameLoadDelegateImplementationCache *cache = &_private->frameLoadDelegateImplementations; 1636 id delegate = _private->frameLoadDelegate; 1637 1638 if (!delegate) { 1639 bzero(cache, sizeof(WebFrameLoadDelegateImplementationCache)); 1640 return; 1641 } 1642 1643 cache->didCancelClientRedirectForFrameFunc = getMethod(delegate, @selector(webView:didCancelClientRedirectForFrame:)); 1644 cache->didChangeLocationWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didChangeLocationWithinPageForFrame:)); 1645 cache->didPushStateWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didPushStateWithinPageForFrame:)); 1646 cache->didReplaceStateWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didReplaceStateWithinPageForFrame:)); 1647 cache->didPopStateWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didPopStateWithinPageForFrame:)); 1648#if JSC_OBJC_API_ENABLED 1649 cache->didCreateJavaScriptContextForFrameFunc = getMethod(delegate, @selector(webView:didCreateJavaScriptContext:forFrame:)); 1650#endif 1651 cache->didClearWindowObjectForFrameFunc = getMethod(delegate, @selector(webView:didClearWindowObject:forFrame:)); 1652 cache->didClearWindowObjectForFrameInScriptWorldFunc = getMethod(delegate, @selector(webView:didClearWindowObjectForFrame:inScriptWorld:)); 1653 cache->didClearInspectorWindowObjectForFrameFunc = getMethod(delegate, @selector(webView:didClearInspectorWindowObject:forFrame:)); 1654 cache->didCommitLoadForFrameFunc = getMethod(delegate, @selector(webView:didCommitLoadForFrame:)); 1655 cache->didFailLoadWithErrorForFrameFunc = getMethod(delegate, @selector(webView:didFailLoadWithError:forFrame:)); 1656 cache->didFailProvisionalLoadWithErrorForFrameFunc = getMethod(delegate, @selector(webView:didFailProvisionalLoadWithError:forFrame:)); 1657 cache->didFinishDocumentLoadForFrameFunc = getMethod(delegate, @selector(webView:didFinishDocumentLoadForFrame:)); 1658 cache->didFinishLoadForFrameFunc = getMethod(delegate, @selector(webView:didFinishLoadForFrame:)); 1659 cache->didFirstLayoutInFrameFunc = getMethod(delegate, @selector(webView:didFirstLayoutInFrame:)); 1660 cache->didFirstVisuallyNonEmptyLayoutInFrameFunc = getMethod(delegate, @selector(webView:didFirstVisuallyNonEmptyLayoutInFrame:)); 1661 cache->didLayoutFunc = getMethod(delegate, @selector(webView:didLayout:)); 1662 cache->didHandleOnloadEventsForFrameFunc = getMethod(delegate, @selector(webView:didHandleOnloadEventsForFrame:)); 1663 cache->didReceiveIconForFrameFunc = getMethod(delegate, @selector(webView:didReceiveIcon:forFrame:)); 1664 cache->didReceiveServerRedirectForProvisionalLoadForFrameFunc = getMethod(delegate, @selector(webView:didReceiveServerRedirectForProvisionalLoadForFrame:)); 1665 cache->didReceiveTitleForFrameFunc = getMethod(delegate, @selector(webView:didReceiveTitle:forFrame:)); 1666 cache->didStartProvisionalLoadForFrameFunc = getMethod(delegate, @selector(webView:didStartProvisionalLoadForFrame:)); 1667 cache->willCloseFrameFunc = getMethod(delegate, @selector(webView:willCloseFrame:)); 1668 cache->willPerformClientRedirectToURLDelayFireDateForFrameFunc = getMethod(delegate, @selector(webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:)); 1669 cache->windowScriptObjectAvailableFunc = getMethod(delegate, @selector(webView:windowScriptObjectAvailable:)); 1670 cache->didDisplayInsecureContentFunc = getMethod(delegate, @selector(webViewDidDisplayInsecureContent:)); 1671 cache->didRunInsecureContentFunc = getMethod(delegate, @selector(webView:didRunInsecureContent:)); 1672 cache->didDetectXSSFunc = getMethod(delegate, @selector(webView:didDetectXSS:)); 1673 cache->didRemoveFrameFromHierarchyFunc = getMethod(delegate, @selector(webView:didRemoveFrameFromHierarchy:)); 1674 1675 // It would be nice to get rid of this code and transition all clients to using didLayout instead of 1676 // didFirstLayoutInFrame and didFirstVisuallyNonEmptyLayoutInFrame. In the meantime, this is required 1677 // for backwards compatibility. 1678 Page* page = core(self); 1679 if (page) { 1680 unsigned milestones = DidFirstLayout; 1681 if (cache->didFirstVisuallyNonEmptyLayoutInFrameFunc) 1682 milestones |= DidFirstVisuallyNonEmptyLayout; 1683 page->addLayoutMilestones(static_cast<LayoutMilestones>(milestones)); 1684 } 1685} 1686 1687- (void)_cacheScriptDebugDelegateImplementations 1688{ 1689 WebScriptDebugDelegateImplementationCache *cache = &_private->scriptDebugDelegateImplementations; 1690 id delegate = _private->scriptDebugDelegate; 1691 1692 if (!delegate) { 1693 bzero(cache, sizeof(WebScriptDebugDelegateImplementationCache)); 1694 return; 1695 } 1696 1697 cache->didParseSourceFunc = getMethod(delegate, @selector(webView:didParseSource:baseLineNumber:fromURL:sourceId:forWebFrame:)); 1698 if (cache->didParseSourceFunc) 1699 cache->didParseSourceExpectsBaseLineNumber = YES; 1700 else { 1701 cache->didParseSourceExpectsBaseLineNumber = NO; 1702 cache->didParseSourceFunc = getMethod(delegate, @selector(webView:didParseSource:fromURL:sourceId:forWebFrame:)); 1703 } 1704 1705 cache->failedToParseSourceFunc = getMethod(delegate, @selector(webView:failedToParseSource:baseLineNumber:fromURL:withError:forWebFrame:)); 1706 cache->didEnterCallFrameFunc = getMethod(delegate, @selector(webView:didEnterCallFrame:sourceId:line:forWebFrame:)); 1707 cache->willExecuteStatementFunc = getMethod(delegate, @selector(webView:willExecuteStatement:sourceId:line:forWebFrame:)); 1708 cache->willLeaveCallFrameFunc = getMethod(delegate, @selector(webView:willLeaveCallFrame:sourceId:line:forWebFrame:)); 1709 1710 cache->exceptionWasRaisedFunc = getMethod(delegate, @selector(webView:exceptionWasRaised:hasHandler:sourceId:line:forWebFrame:)); 1711 if (cache->exceptionWasRaisedFunc) 1712 cache->exceptionWasRaisedExpectsHasHandlerFlag = YES; 1713 else { 1714 cache->exceptionWasRaisedExpectsHasHandlerFlag = NO; 1715 cache->exceptionWasRaisedFunc = getMethod(delegate, @selector(webView:exceptionWasRaised:sourceId:line:forWebFrame:)); 1716 } 1717} 1718 1719- (void)_cacheHistoryDelegateImplementations 1720{ 1721 WebHistoryDelegateImplementationCache *cache = &_private->historyDelegateImplementations; 1722 id delegate = _private->historyDelegate; 1723 1724 if (!delegate) { 1725 bzero(cache, sizeof(WebHistoryDelegateImplementationCache)); 1726 return; 1727 } 1728 1729 cache->navigatedFunc = getMethod(delegate, @selector(webView:didNavigateWithNavigationData:inFrame:)); 1730 cache->clientRedirectFunc = getMethod(delegate, @selector(webView:didPerformClientRedirectFromURL:toURL:inFrame:)); 1731 cache->serverRedirectFunc = getMethod(delegate, @selector(webView:didPerformServerRedirectFromURL:toURL:inFrame:)); 1732 cache->deprecatedSetTitleFunc = getMethod(delegate, @selector(webView:updateHistoryTitle:forURL:)); 1733 cache->setTitleFunc = getMethod(delegate, @selector(webView:updateHistoryTitle:forURL:inFrame:)); 1734 cache->populateVisitedLinksFunc = getMethod(delegate, @selector(populateVisitedLinksForWebView:)); 1735} 1736 1737- (id)_policyDelegateForwarder 1738{ 1739 if (!_private->policyDelegateForwarder) 1740 _private->policyDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->policyDelegate defaultTarget:[WebDefaultPolicyDelegate sharedPolicyDelegate]]; 1741 return _private->policyDelegateForwarder; 1742} 1743 1744- (id)_UIDelegateForwarder 1745{ 1746 if (!_private->UIDelegateForwarder) 1747 _private->UIDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->UIDelegate defaultTarget:[WebDefaultUIDelegate sharedUIDelegate]]; 1748 return _private->UIDelegateForwarder; 1749} 1750 1751- (id)_editingDelegateForwarder 1752{ 1753 // This can be called during window deallocation by QTMovieView in the QuickTime Cocoa Plug-in. 1754 // Not sure if that is a bug or not. 1755 if (!_private) 1756 return nil; 1757 1758 if (!_private->editingDelegateForwarder) 1759 _private->editingDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->editingDelegate defaultTarget:[WebDefaultEditingDelegate sharedEditingDelegate]]; 1760 return _private->editingDelegateForwarder; 1761} 1762 1763- (void)_closeWindow 1764{ 1765 [[self _UIDelegateForwarder] webViewClose:self]; 1766} 1767 1768+ (void)_unregisterViewClassAndRepresentationClassForMIMEType:(NSString *)MIMEType 1769{ 1770 [[WebFrameView _viewTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType]; 1771 [[WebDataSource _repTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType]; 1772 1773 // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed) 1774 // in the WebCore MIMEType registry. For now we're doing this in a safe, limited manner 1775 // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness 1776 MIMETypeRegistry::getSupportedNonImageMIMETypes().remove(MIMEType); 1777} 1778 1779+ (void)_registerViewClass:(Class)viewClass representationClass:(Class)representationClass forURLScheme:(NSString *)URLScheme 1780{ 1781 NSString *MIMEType = [self _generatedMIMETypeForURLScheme:URLScheme]; 1782 [self registerViewClass:viewClass representationClass:representationClass forMIMEType:MIMEType]; 1783 1784 // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed) 1785 // in the WebCore MIMEType registry. For now we're doing this in a safe, limited manner 1786 // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness 1787 if ([viewClass class] == [WebHTMLView class]) 1788 MIMETypeRegistry::getSupportedNonImageMIMETypes().add(MIMEType); 1789 1790 // This is used to make _representationExistsForURLScheme faster. 1791 // Without this set, we'd have to create the MIME type each time. 1792 if (schemesWithRepresentationsSet == nil) { 1793 schemesWithRepresentationsSet = [[NSMutableSet alloc] init]; 1794 } 1795 [schemesWithRepresentationsSet addObject:[[[URLScheme lowercaseString] copy] autorelease]]; 1796} 1797 1798+ (NSString *)_generatedMIMETypeForURLScheme:(NSString *)URLScheme 1799{ 1800 return [@"x-apple-web-kit/" stringByAppendingString:[URLScheme lowercaseString]]; 1801} 1802 1803+ (BOOL)_representationExistsForURLScheme:(NSString *)URLScheme 1804{ 1805 return [schemesWithRepresentationsSet containsObject:[URLScheme lowercaseString]]; 1806} 1807 1808+ (BOOL)_canHandleRequest:(NSURLRequest *)request forMainFrame:(BOOL)forMainFrame 1809{ 1810 // FIXME: If <rdar://problem/5217309> gets fixed, this check can be removed. 1811 if (!request) 1812 return NO; 1813 1814 if ([NSURLConnection canHandleRequest:request]) 1815 return YES; 1816 1817 NSString *scheme = [[request URL] scheme]; 1818 1819 // Representations for URL schemes work at the top level. 1820 if (forMainFrame && [self _representationExistsForURLScheme:scheme]) 1821 return YES; 1822 1823 if ([scheme _webkit_isCaseInsensitiveEqualToString:@"applewebdata"]) 1824 return YES; 1825 1826#if ENABLE(BLOB) 1827 if ([scheme _webkit_isCaseInsensitiveEqualToString:@"blob"]) 1828 return YES; 1829#endif 1830 1831 return NO; 1832} 1833 1834+ (BOOL)_canHandleRequest:(NSURLRequest *)request 1835{ 1836 return [self _canHandleRequest:request forMainFrame:YES]; 1837} 1838 1839+ (NSString *)_decodeData:(NSData *)data 1840{ 1841 HTMLNames::init(); // this method is used for importing bookmarks at startup, so HTMLNames are likely to be uninitialized yet 1842 RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("text/html"); // bookmark files are HTML 1843 String result = decoder->decode(static_cast<const char*>([data bytes]), [data length]); 1844 result.append(decoder->flush()); 1845 return result; 1846} 1847 1848- (void)_pushPerformingProgrammaticFocus 1849{ 1850 _private->programmaticFocusCount++; 1851} 1852 1853- (void)_popPerformingProgrammaticFocus 1854{ 1855 _private->programmaticFocusCount--; 1856} 1857 1858- (BOOL)_isPerformingProgrammaticFocus 1859{ 1860 return _private->programmaticFocusCount != 0; 1861} 1862 1863- (void)_didChangeValueForKey: (NSString *)key 1864{ 1865 LOG (Bindings, "calling didChangeValueForKey: %@", key); 1866 [self didChangeValueForKey: key]; 1867} 1868 1869- (void)_willChangeValueForKey: (NSString *)key 1870{ 1871 LOG (Bindings, "calling willChangeValueForKey: %@", key); 1872 [self willChangeValueForKey: key]; 1873} 1874 1875+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key { 1876 static NSSet *manualNotifyKeys = nil; 1877 if (!manualNotifyKeys) 1878 manualNotifyKeys = [[NSSet alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey, 1879 _WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, _WebMainFrameDocumentKey, 1880 nil]; 1881 if ([manualNotifyKeys containsObject:key]) 1882 return NO; 1883 return YES; 1884} 1885 1886- (NSArray *)_declaredKeys { 1887 static NSArray *declaredKeys = nil; 1888 if (!declaredKeys) 1889 declaredKeys = [[NSArray alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey, 1890 _WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, _WebMainFrameDocumentKey, nil]; 1891 return declaredKeys; 1892} 1893 1894- (void)setObservationInfo:(void *)info 1895{ 1896 _private->observationInfo = info; 1897} 1898 1899- (void *)observationInfo 1900{ 1901 return _private->observationInfo; 1902} 1903 1904- (void)_willChangeBackForwardKeys 1905{ 1906 [self _willChangeValueForKey: _WebCanGoBackKey]; 1907 [self _willChangeValueForKey: _WebCanGoForwardKey]; 1908} 1909 1910- (void)_didChangeBackForwardKeys 1911{ 1912 [self _didChangeValueForKey: _WebCanGoBackKey]; 1913 [self _didChangeValueForKey: _WebCanGoForwardKey]; 1914} 1915 1916- (void)_didStartProvisionalLoadForFrame:(WebFrame *)frame 1917{ 1918 if (needsSelfRetainWhileLoadingQuirk()) 1919 [self retain]; 1920 1921 [self _willChangeBackForwardKeys]; 1922 if (frame == [self mainFrame]){ 1923 // Force an observer update by sending a will/did. 1924 [self _willChangeValueForKey: _WebIsLoadingKey]; 1925 [self _didChangeValueForKey: _WebIsLoadingKey]; 1926 1927 [self _willChangeValueForKey: _WebMainFrameURLKey]; 1928 } 1929 1930 [NSApp setWindowsNeedUpdate:YES]; 1931 1932#if ENABLE(FULLSCREEN_API) 1933 Document* document = core([frame DOMDocument]); 1934 if (Element* element = document ? document->webkitCurrentFullScreenElement() : 0) { 1935 SEL selector = @selector(webView:closeFullScreenWithListener:); 1936 if (_private->UIDelegate && [_private->UIDelegate respondsToSelector:selector]) { 1937 WebKitFullScreenListener *listener = [[WebKitFullScreenListener alloc] initWithElement:element]; 1938 CallUIDelegate(self, selector, listener); 1939 [listener release]; 1940 } else if (_private->newFullscreenController && [_private->newFullscreenController isFullScreen]) { 1941 [_private->newFullscreenController close]; 1942 } 1943 } 1944#endif 1945} 1946 1947- (void)_didCommitLoadForFrame:(WebFrame *)frame 1948{ 1949 if (frame == [self mainFrame]) 1950 [self _didChangeValueForKey: _WebMainFrameURLKey]; 1951 [NSApp setWindowsNeedUpdate:YES]; 1952} 1953 1954- (void)_didFinishLoadForFrame:(WebFrame *)frame 1955{ 1956 if (needsSelfRetainWhileLoadingQuirk()) 1957 [self performSelector:@selector(release) withObject:nil afterDelay:0]; 1958 1959 [self _didChangeBackForwardKeys]; 1960 if (frame == [self mainFrame]){ 1961 // Force an observer update by sending a will/did. 1962 [self _willChangeValueForKey: _WebIsLoadingKey]; 1963 [self _didChangeValueForKey: _WebIsLoadingKey]; 1964 } 1965 [NSApp setWindowsNeedUpdate:YES]; 1966} 1967 1968- (void)_didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame 1969{ 1970 if (needsSelfRetainWhileLoadingQuirk()) 1971 [self performSelector:@selector(release) withObject:nil afterDelay:0]; 1972 1973 [self _didChangeBackForwardKeys]; 1974 if (frame == [self mainFrame]){ 1975 // Force an observer update by sending a will/did. 1976 [self _willChangeValueForKey: _WebIsLoadingKey]; 1977 [self _didChangeValueForKey: _WebIsLoadingKey]; 1978 } 1979 [NSApp setWindowsNeedUpdate:YES]; 1980} 1981 1982- (void)_didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame 1983{ 1984 if (needsSelfRetainWhileLoadingQuirk()) 1985 [self performSelector:@selector(release) withObject:nil afterDelay:0]; 1986 1987 [self _didChangeBackForwardKeys]; 1988 if (frame == [self mainFrame]){ 1989 // Force an observer update by sending a will/did. 1990 [self _willChangeValueForKey: _WebIsLoadingKey]; 1991 [self _didChangeValueForKey: _WebIsLoadingKey]; 1992 1993 [self _didChangeValueForKey: _WebMainFrameURLKey]; 1994 } 1995 [NSApp setWindowsNeedUpdate:YES]; 1996} 1997 1998- (NSCachedURLResponse *)_cachedResponseForURL:(NSURL *)URL 1999{ 2000 RetainPtr<NSMutableURLRequest *> request = adoptNS([[NSMutableURLRequest alloc] initWithURL:URL]); 2001 [request _web_setHTTPUserAgent:[self userAgentForURL:URL]]; 2002 NSCachedURLResponse *cachedResponse; 2003 2004 if (!_private->page) 2005 return nil; 2006 2007 if (CFURLStorageSessionRef storageSession = _private->page->mainFrame()->loader()->networkingContext()->storageSession().platformSession()) 2008 cachedResponse = WKCachedResponseForRequest(storageSession, request.get()); 2009 else 2010 cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:request.get()]; 2011 2012 return cachedResponse; 2013} 2014 2015- (void)_writeImageForElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard 2016{ 2017 NSURL *linkURL = [element objectForKey:WebElementLinkURLKey]; 2018 DOMElement *domElement = [element objectForKey:WebElementDOMNodeKey]; 2019 [pasteboard _web_writeImage:(NSImage *)(domElement ? nil : [element objectForKey:WebElementImageKey]) 2020 element:domElement 2021 URL:linkURL ? linkURL : (NSURL *)[element objectForKey:WebElementImageURLKey] 2022 title:[element objectForKey:WebElementImageAltStringKey] 2023 archive:[[element objectForKey:WebElementDOMNodeKey] webArchive] 2024 types:types 2025 source:nil]; 2026} 2027 2028- (void)_writeLinkElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard 2029{ 2030 [pasteboard _web_writeURL:[element objectForKey:WebElementLinkURLKey] 2031 andTitle:[element objectForKey:WebElementLinkLabelKey] 2032 types:types]; 2033} 2034 2035#if ENABLE(DRAG_SUPPORT) 2036- (void)_setInitiatedDrag:(BOOL)initiatedDrag 2037{ 2038 if (!_private->page) 2039 return; 2040 _private->page->dragController()->setDidInitiateDrag(initiatedDrag); 2041} 2042#endif 2043 2044#if ENABLE(DASHBOARD_SUPPORT) 2045 2046#define DASHBOARD_CONTROL_LABEL @"control" 2047 2048- (void)_addControlRect:(NSRect)bounds clip:(NSRect)clip fromView:(NSView *)view toDashboardRegions:(NSMutableDictionary *)regions 2049{ 2050 NSRect adjustedBounds = bounds; 2051 adjustedBounds.origin = [self convertPoint:bounds.origin fromView:view]; 2052 adjustedBounds.origin.y = [self bounds].size.height - adjustedBounds.origin.y; 2053 adjustedBounds.size = bounds.size; 2054 2055 NSRect adjustedClip; 2056 adjustedClip.origin = [self convertPoint:clip.origin fromView:view]; 2057 adjustedClip.origin.y = [self bounds].size.height - adjustedClip.origin.y; 2058 adjustedClip.size = clip.size; 2059 2060 WebDashboardRegion *region = [[WebDashboardRegion alloc] initWithRect:adjustedBounds 2061 clip:adjustedClip type:WebDashboardRegionTypeScrollerRectangle]; 2062 NSMutableArray *scrollerRegions = [regions objectForKey:DASHBOARD_CONTROL_LABEL]; 2063 if (!scrollerRegions) { 2064 scrollerRegions = [[NSMutableArray alloc] init]; 2065 [regions setObject:scrollerRegions forKey:DASHBOARD_CONTROL_LABEL]; 2066 [scrollerRegions release]; 2067 } 2068 [scrollerRegions addObject:region]; 2069 [region release]; 2070} 2071 2072- (void)_addScrollerDashboardRegionsForFrameView:(FrameView*)frameView dashboardRegions:(NSMutableDictionary *)regions 2073{ 2074 NSView *documentView = [[kit(frameView->frame()) frameView] documentView]; 2075 2076 const HashSet<RefPtr<Widget> >* children = frameView->children(); 2077 HashSet<RefPtr<Widget> >::const_iterator end = children->end(); 2078 for (HashSet<RefPtr<Widget> >::const_iterator it = children->begin(); it != end; ++it) { 2079 Widget* widget = (*it).get(); 2080 if (widget->isFrameView()) { 2081 [self _addScrollerDashboardRegionsForFrameView:toFrameView(widget) dashboardRegions:regions]; 2082 continue; 2083 } 2084 2085 if (!widget->isScrollbar()) 2086 continue; 2087 2088 // FIXME: This should really pass an appropriate clip, but our first try got it wrong, and 2089 // it's not common to need this to be correct in Dashboard widgets. 2090 NSRect bounds = widget->frameRect(); 2091 [self _addControlRect:bounds clip:bounds fromView:documentView toDashboardRegions:regions]; 2092 } 2093} 2094 2095- (void)_addScrollerDashboardRegions:(NSMutableDictionary *)regions from:(NSArray *)views 2096{ 2097 // Add scroller regions for NSScroller and WebCore scrollbars 2098 NSUInteger count = [views count]; 2099 for (NSUInteger i = 0; i < count; i++) { 2100 NSView *view = [views objectAtIndex:i]; 2101 2102 if ([view isKindOfClass:[WebHTMLView class]]) { 2103 if (Frame* coreFrame = core([(WebHTMLView*)view _frame])) { 2104 if (FrameView* coreView = coreFrame->view()) 2105 [self _addScrollerDashboardRegionsForFrameView:coreView dashboardRegions:regions]; 2106 } 2107 } else if ([view isKindOfClass:[NSScroller class]]) { 2108 // AppKit places absent scrollers at -100,-100 2109 if ([view frame].origin.y < 0) 2110 continue; 2111 [self _addControlRect:[view bounds] clip:[view visibleRect] fromView:view toDashboardRegions:regions]; 2112 } 2113 [self _addScrollerDashboardRegions:regions from:[view subviews]]; 2114 } 2115} 2116 2117- (void)_addScrollerDashboardRegions:(NSMutableDictionary *)regions 2118{ 2119 [self _addScrollerDashboardRegions:regions from:[self subviews]]; 2120} 2121 2122- (NSDictionary *)_dashboardRegions 2123{ 2124 // Only return regions from main frame. 2125 Frame* mainFrame = [self _mainCoreFrame]; 2126 if (!mainFrame) 2127 return nil; 2128 2129 const Vector<AnnotatedRegionValue>& regions = mainFrame->document()->annotatedRegions(); 2130 size_t size = regions.size(); 2131 2132 NSMutableDictionary *webRegions = [NSMutableDictionary dictionaryWithCapacity:size]; 2133 for (size_t i = 0; i < size; i++) { 2134 const AnnotatedRegionValue& region = regions[i]; 2135 2136 if (region.type == StyleDashboardRegion::None) 2137 continue; 2138 2139 NSString *label = region.label; 2140 WebDashboardRegionType type = WebDashboardRegionTypeNone; 2141 if (region.type == StyleDashboardRegion::Circle) 2142 type = WebDashboardRegionTypeCircle; 2143 else if (region.type == StyleDashboardRegion::Rectangle) 2144 type = WebDashboardRegionTypeRectangle; 2145 NSMutableArray *regionValues = [webRegions objectForKey:label]; 2146 if (!regionValues) { 2147 regionValues = [[NSMutableArray alloc] initWithCapacity:1]; 2148 [webRegions setObject:regionValues forKey:label]; 2149 [regionValues release]; 2150 } 2151 2152 WebDashboardRegion *webRegion = [[WebDashboardRegion alloc] initWithRect:pixelSnappedIntRect(region.bounds) clip:pixelSnappedIntRect(region.clip) type:type]; 2153 [regionValues addObject:webRegion]; 2154 [webRegion release]; 2155 } 2156 2157 [self _addScrollerDashboardRegions:webRegions]; 2158 2159 return webRegions; 2160} 2161 2162- (void)_setDashboardBehavior:(WebDashboardBehavior)behavior to:(BOOL)flag 2163{ 2164 // FIXME: Remove this blanket assignment once Dashboard and Dashcode implement 2165 // specific support for the backward compatibility mode flag. 2166 if (behavior == WebDashboardBehaviorAllowWheelScrolling && flag == NO && _private->page) 2167 _private->page->settings()->setUsesDashboardBackwardCompatibilityMode(true); 2168 2169 switch (behavior) { 2170 case WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows: { 2171 _private->dashboardBehaviorAlwaysSendMouseEventsToAllWindows = flag; 2172 break; 2173 } 2174 case WebDashboardBehaviorAlwaysSendActiveNullEventsToPlugIns: { 2175 _private->dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns = flag; 2176 break; 2177 } 2178 case WebDashboardBehaviorAlwaysAcceptsFirstMouse: { 2179 _private->dashboardBehaviorAlwaysAcceptsFirstMouse = flag; 2180 break; 2181 } 2182 case WebDashboardBehaviorAllowWheelScrolling: { 2183 _private->dashboardBehaviorAllowWheelScrolling = flag; 2184 break; 2185 } 2186 case WebDashboardBehaviorUseBackwardCompatibilityMode: { 2187 if (_private->page) 2188 _private->page->settings()->setUsesDashboardBackwardCompatibilityMode(flag); 2189#if ENABLE(LEGACY_CSS_VENDOR_PREFIXES) 2190 RuntimeEnabledFeatures::setLegacyCSSVendorPrefixesEnabled(flag); 2191#endif 2192 break; 2193 } 2194 } 2195 2196 // Pre-HTML5 parser quirks should be enabled if Dashboard is in backward 2197 // compatibility mode. See <rdar://problem/8175982>. 2198 if (_private->page) 2199 _private->page->settings()->setUsePreHTML5ParserQuirks([self _needsPreHTML5ParserQuirks]); 2200} 2201 2202- (BOOL)_dashboardBehavior:(WebDashboardBehavior)behavior 2203{ 2204 switch (behavior) { 2205 case WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows: { 2206 return _private->dashboardBehaviorAlwaysSendMouseEventsToAllWindows; 2207 } 2208 case WebDashboardBehaviorAlwaysSendActiveNullEventsToPlugIns: { 2209 return _private->dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns; 2210 } 2211 case WebDashboardBehaviorAlwaysAcceptsFirstMouse: { 2212 return _private->dashboardBehaviorAlwaysAcceptsFirstMouse; 2213 } 2214 case WebDashboardBehaviorAllowWheelScrolling: { 2215 return _private->dashboardBehaviorAllowWheelScrolling; 2216 } 2217 case WebDashboardBehaviorUseBackwardCompatibilityMode: { 2218 return _private->page && _private->page->settings()->usesDashboardBackwardCompatibilityMode(); 2219 } 2220 } 2221 return NO; 2222} 2223 2224#endif /* ENABLE(DASHBOARD_SUPPORT) */ 2225 2226+ (void)_setShouldUseFontSmoothing:(BOOL)f 2227{ 2228 Font::setShouldUseSmoothing(f); 2229} 2230 2231+ (BOOL)_shouldUseFontSmoothing 2232{ 2233 return Font::shouldUseSmoothing(); 2234} 2235 2236+ (void)_setUsesTestModeFocusRingColor:(BOOL)f 2237{ 2238 setUsesTestModeFocusRingColor(f); 2239} 2240 2241+ (BOOL)_usesTestModeFocusRingColor 2242{ 2243 return usesTestModeFocusRingColor(); 2244} 2245 2246- (void)setAlwaysShowVerticalScroller:(BOOL)flag 2247{ 2248 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView]; 2249 if (flag) { 2250 [scrollview setVerticalScrollingMode:ScrollbarAlwaysOn andLock:YES]; 2251 } else { 2252 [scrollview setVerticalScrollingModeLocked:NO]; 2253 [scrollview setVerticalScrollingMode:ScrollbarAuto andLock:NO]; 2254 } 2255} 2256 2257- (BOOL)alwaysShowVerticalScroller 2258{ 2259 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView]; 2260 return [scrollview verticalScrollingModeLocked] && [scrollview verticalScrollingMode] == ScrollbarAlwaysOn; 2261} 2262 2263- (void)setAlwaysShowHorizontalScroller:(BOOL)flag 2264{ 2265 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView]; 2266 if (flag) { 2267 [scrollview setHorizontalScrollingMode:ScrollbarAlwaysOn andLock:YES]; 2268 } else { 2269 [scrollview setHorizontalScrollingModeLocked:NO]; 2270 [scrollview setHorizontalScrollingMode:ScrollbarAuto andLock:NO]; 2271 } 2272} 2273 2274- (void)setProhibitsMainFrameScrolling:(BOOL)prohibits 2275{ 2276 if (Frame* mainFrame = [self _mainCoreFrame]) 2277 mainFrame->view()->setProhibitsScrolling(prohibits); 2278} 2279 2280- (BOOL)alwaysShowHorizontalScroller 2281{ 2282 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView]; 2283 return [scrollview horizontalScrollingModeLocked] && [scrollview horizontalScrollingMode] == ScrollbarAlwaysOn; 2284} 2285 2286- (void)_setInViewSourceMode:(BOOL)flag 2287{ 2288 if (Frame* mainFrame = [self _mainCoreFrame]) 2289 mainFrame->setInViewSourceMode(flag); 2290} 2291 2292- (BOOL)_inViewSourceMode 2293{ 2294 Frame* mainFrame = [self _mainCoreFrame]; 2295 return mainFrame && mainFrame->inViewSourceMode(); 2296} 2297 2298- (void)_setUseFastImageScalingMode:(BOOL)flag 2299{ 2300 if (_private->page && _private->page->inLowQualityImageInterpolationMode() != flag) { 2301 _private->page->setInLowQualityImageInterpolationMode(flag); 2302 [self setNeedsDisplay:YES]; 2303 } 2304} 2305 2306- (BOOL)_inFastImageScalingMode 2307{ 2308 if (_private->page) 2309 return _private->page->inLowQualityImageInterpolationMode(); 2310 return NO; 2311} 2312 2313- (BOOL)_cookieEnabled 2314{ 2315 if (_private->page) 2316 return _private->page->settings()->cookieEnabled(); 2317 return YES; 2318} 2319 2320- (void)_setCookieEnabled:(BOOL)enable 2321{ 2322 if (_private->page) 2323 _private->page->settings()->setCookieEnabled(enable); 2324} 2325 2326- (void)_setAdditionalWebPlugInPaths:(NSArray *)newPaths 2327{ 2328 if (!_private->pluginDatabase) 2329 _private->pluginDatabase = [[WebPluginDatabase alloc] init]; 2330 2331 [_private->pluginDatabase setPlugInPaths:newPaths]; 2332 [_private->pluginDatabase refresh]; 2333} 2334 2335- (void)_attachScriptDebuggerToAllFrames 2336{ 2337 for (Frame* frame = [self _mainCoreFrame]; frame; frame = frame->tree()->traverseNext()) 2338 [kit(frame) _attachScriptDebugger]; 2339} 2340 2341- (void)_detachScriptDebuggerFromAllFrames 2342{ 2343 for (Frame* frame = [self _mainCoreFrame]; frame; frame = frame->tree()->traverseNext()) 2344 [kit(frame) _detachScriptDebugger]; 2345} 2346 2347- (void)setBackgroundColor:(NSColor *)backgroundColor 2348{ 2349 if ([_private->backgroundColor isEqual:backgroundColor]) 2350 return; 2351 2352 id old = _private->backgroundColor; 2353 _private->backgroundColor = [backgroundColor retain]; 2354 [old release]; 2355 2356 [[self mainFrame] _updateBackgroundAndUpdatesWhileOffscreen]; 2357} 2358 2359- (NSColor *)backgroundColor 2360{ 2361 return _private->backgroundColor; 2362} 2363 2364- (BOOL)defersCallbacks 2365{ 2366 if (!_private->page) 2367 return NO; 2368 return _private->page->defersLoading(); 2369} 2370 2371- (void)setDefersCallbacks:(BOOL)defer 2372{ 2373 if (!_private->page) 2374 return; 2375 return _private->page->setDefersLoading(defer); 2376} 2377 2378// For backwards compatibility with the WebBackForwardList API, we honor both 2379// a per-WebView and a per-preferences setting for whether to use the page cache. 2380 2381- (BOOL)usesPageCache 2382{ 2383 return _private->usesPageCache && [[self preferences] usesPageCache]; 2384} 2385 2386- (void)setUsesPageCache:(BOOL)usesPageCache 2387{ 2388 _private->usesPageCache = usesPageCache; 2389 2390 // Update our own settings and post the public notification only 2391 [self _preferencesChanged:[self preferences]]; 2392 [[self preferences] _postPreferencesChangedAPINotification]; 2393} 2394 2395- (WebHistoryItem *)_globalHistoryItem 2396{ 2397 if (!_private) 2398 return nil; 2399 2400 return kit(_private->_globalHistoryItem.get()); 2401} 2402 2403- (void)_setGlobalHistoryItem:(HistoryItem*)historyItem 2404{ 2405 _private->_globalHistoryItem = historyItem; 2406} 2407 2408- (WebTextIterator *)textIteratorForRect:(NSRect)rect 2409{ 2410 IntPoint rectStart(rect.origin.x, rect.origin.y); 2411 IntPoint rectEnd(rect.origin.x + rect.size.width, rect.origin.y + rect.size.height); 2412 2413 Frame* coreFrame = [self _mainCoreFrame]; 2414 if (!coreFrame) 2415 return nil; 2416 2417 VisibleSelection selectionInsideRect(coreFrame->visiblePositionForPoint(rectStart), coreFrame->visiblePositionForPoint(rectEnd)); 2418 2419 return [[[WebTextIterator alloc] initWithRange:kit(selectionInsideRect.toNormalizedRange().get())] autorelease]; 2420} 2421 2422- (void)handleAuthenticationForResource:(id)identifier challenge:(NSURLAuthenticationChallenge *)challenge fromDataSource:(WebDataSource *)dataSource 2423{ 2424 NSWindow *window = [self hostWindow] ? [self hostWindow] : [self window]; 2425 [[WebPanelAuthenticationHandler sharedHandler] startAuthentication:challenge window:window]; 2426} 2427 2428- (void)_clearUndoRedoOperations 2429{ 2430 if (!_private->page) 2431 return; 2432 _private->page->clearUndoRedoOperations(); 2433} 2434 2435- (void)_executeCoreCommandByName:(NSString *)name value:(NSString *)value 2436{ 2437 Frame* coreFrame = [self _mainCoreFrame]; 2438 if (!coreFrame) 2439 return; 2440 coreFrame->editor().command(name).execute(value); 2441} 2442 2443- (void)_setCustomHTMLTokenizerTimeDelay:(double)timeDelay 2444{ 2445 if (!_private->page) 2446 return; 2447 return _private->page->setCustomHTMLTokenizerTimeDelay(timeDelay); 2448} 2449 2450- (void)_setCustomHTMLTokenizerChunkSize:(int)chunkSize 2451{ 2452 if (!_private->page) 2453 return; 2454 return _private->page->setCustomHTMLTokenizerChunkSize(chunkSize); 2455} 2456 2457- (void)_clearMainFrameName 2458{ 2459 _private->page->mainFrame()->tree()->clearName(); 2460} 2461 2462- (void)setSelectTrailingWhitespaceEnabled:(BOOL)flag 2463{ 2464 if (_private->page->settings()->selectTrailingWhitespaceEnabled() != flag) { 2465 _private->page->settings()->setSelectTrailingWhitespaceEnabled(flag); 2466 [self setSmartInsertDeleteEnabled:!flag]; 2467 } 2468} 2469 2470- (BOOL)isSelectTrailingWhitespaceEnabled 2471{ 2472 return _private->page->settings()->selectTrailingWhitespaceEnabled(); 2473} 2474 2475- (void)setMemoryCacheDelegateCallsEnabled:(BOOL)enabled 2476{ 2477 _private->page->setMemoryCacheClientCallsEnabled(enabled); 2478} 2479 2480- (BOOL)areMemoryCacheDelegateCallsEnabled 2481{ 2482 return _private->page->areMemoryCacheClientCallsEnabled(); 2483} 2484 2485+ (NSCursor *)_pointingHandCursor 2486{ 2487 return handCursor().platformCursor(); 2488} 2489 2490- (BOOL)_postsAcceleratedCompositingNotifications 2491{ 2492#if USE(ACCELERATED_COMPOSITING) 2493 return _private->postsAcceleratedCompositingNotifications; 2494#else 2495 return NO; 2496#endif 2497 2498} 2499- (void)_setPostsAcceleratedCompositingNotifications:(BOOL)flag 2500{ 2501#if USE(ACCELERATED_COMPOSITING) 2502 _private->postsAcceleratedCompositingNotifications = flag; 2503#endif 2504} 2505 2506- (BOOL)_isUsingAcceleratedCompositing 2507{ 2508#if USE(ACCELERATED_COMPOSITING) 2509 Frame* coreFrame = [self _mainCoreFrame]; 2510 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) { 2511 NSView *documentView = [[kit(frame) frameView] documentView]; 2512 if ([documentView isKindOfClass:[WebHTMLView class]] && [(WebHTMLView *)documentView _isUsingAcceleratedCompositing]) 2513 return YES; 2514 } 2515#endif 2516 return NO; 2517} 2518 2519- (void)_setBaseCTM:(CGAffineTransform)transform forContext:(CGContextRef)context 2520{ 2521 WKSetBaseCTM(context, transform); 2522} 2523 2524- (BOOL)interactiveFormValidationEnabled 2525{ 2526 return _private->interactiveFormValidationEnabled; 2527} 2528 2529- (void)setInteractiveFormValidationEnabled:(BOOL)enabled 2530{ 2531 _private->interactiveFormValidationEnabled = enabled; 2532} 2533 2534- (int)validationMessageTimerMagnification 2535{ 2536 return _private->validationMessageTimerMagnification; 2537} 2538 2539- (void)setValidationMessageTimerMagnification:(int)newValue 2540{ 2541 _private->validationMessageTimerMagnification = newValue; 2542} 2543 2544- (BOOL)_isSoftwareRenderable 2545{ 2546#if USE(ACCELERATED_COMPOSITING) 2547 Frame* coreFrame = [self _mainCoreFrame]; 2548 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) { 2549 if (FrameView* view = frame->view()) { 2550 if (!view->isSoftwareRenderable()) 2551 return NO; 2552 } 2553 } 2554#endif 2555 return YES; 2556} 2557 2558- (void)_setIncludesFlattenedCompositingLayersWhenDrawingToBitmap:(BOOL)flag 2559{ 2560 _private->includesFlattenedCompositingLayersWhenDrawingToBitmap = flag; 2561} 2562 2563- (BOOL)_includesFlattenedCompositingLayersWhenDrawingToBitmap 2564{ 2565 return _private->includesFlattenedCompositingLayersWhenDrawingToBitmap; 2566} 2567 2568- (void)setTracksRepaints:(BOOL)flag 2569{ 2570 Frame* coreFrame = [self _mainCoreFrame]; 2571 if (FrameView* view = coreFrame->view()) 2572 view->setTracksRepaints(flag); 2573} 2574 2575- (BOOL)isTrackingRepaints 2576{ 2577 Frame* coreFrame = [self _mainCoreFrame]; 2578 if (FrameView* view = coreFrame->view()) 2579 return view->isTrackingRepaints(); 2580 2581 return NO; 2582} 2583 2584- (void)resetTrackedRepaints 2585{ 2586 Frame* coreFrame = [self _mainCoreFrame]; 2587 if (FrameView* view = coreFrame->view()) 2588 view->resetTrackedRepaints(); 2589} 2590 2591- (NSArray*)trackedRepaintRects 2592{ 2593 Frame* coreFrame = [self _mainCoreFrame]; 2594 FrameView* view = coreFrame->view(); 2595 if (!view || !view->isTrackingRepaints()) 2596 return nil; 2597 2598 const Vector<IntRect>& repaintRects = view->trackedRepaintRects(); 2599 NSMutableArray* rectsArray = [[NSMutableArray alloc] initWithCapacity:repaintRects.size()]; 2600 2601 for (unsigned i = 0; i < repaintRects.size(); ++i) 2602 [rectsArray addObject:[NSValue valueWithRect:pixelSnappedIntRect(repaintRects[i])]]; 2603 2604 return [rectsArray autorelease]; 2605} 2606 2607- (NSPasteboard *)_insertionPasteboard 2608{ 2609 return _private ? _private->insertionPasteboard : nil; 2610} 2611 2612+ (void)_addOriginAccessWhitelistEntryWithSourceOrigin:(NSString *)sourceOrigin destinationProtocol:(NSString *)destinationProtocol destinationHost:(NSString *)destinationHost allowDestinationSubdomains:(BOOL)allowDestinationSubdomains 2613{ 2614 SecurityPolicy::addOriginAccessWhitelistEntry(*SecurityOrigin::createFromString(sourceOrigin), destinationProtocol, destinationHost, allowDestinationSubdomains); 2615} 2616 2617+ (void)_removeOriginAccessWhitelistEntryWithSourceOrigin:(NSString *)sourceOrigin destinationProtocol:(NSString *)destinationProtocol destinationHost:(NSString *)destinationHost allowDestinationSubdomains:(BOOL)allowDestinationSubdomains 2618{ 2619 SecurityPolicy::removeOriginAccessWhitelistEntry(*SecurityOrigin::createFromString(sourceOrigin), destinationProtocol, destinationHost, allowDestinationSubdomains); 2620} 2621 2622+ (void)_resetOriginAccessWhitelists 2623{ 2624 SecurityPolicy::resetOriginAccessWhitelists(); 2625} 2626 2627- (BOOL)_isViewVisible 2628{ 2629 if (![self window]) 2630 return false; 2631 2632 if (![[self window] isVisible]) 2633 return false; 2634 2635 if ([self isHiddenOrHasHiddenAncestor]) 2636 return false; 2637 2638 return true; 2639} 2640 2641- (void)_updateVisibilityState 2642{ 2643 if (_private && _private->page) 2644 [self _setVisibilityState:([self _isViewVisible] ? WebPageVisibilityStateVisible : WebPageVisibilityStateHidden) isInitialState:NO]; 2645} 2646 2647- (void)_updateActiveState 2648{ 2649 if (_private && _private->page) 2650 _private->page->focusController()->setActive([[self window] _hasKeyAppearance]); 2651} 2652 2653static Vector<String> toStringVector(NSArray* patterns) 2654{ 2655 Vector<String> patternsVector; 2656 2657 NSUInteger count = [patterns count]; 2658 if (!count) 2659 return patternsVector; 2660 2661 for (NSUInteger i = 0; i < count; ++i) { 2662 id entry = [patterns objectAtIndex:i]; 2663 if ([entry isKindOfClass:[NSString class]]) 2664 patternsVector.append(String((NSString *)entry)); 2665 } 2666 return patternsVector; 2667} 2668 2669+ (void)_addUserScriptToGroup:(NSString *)groupName world:(WebScriptWorld *)world source:(NSString *)source url:(NSURL *)url 2670 whitelist:(NSArray *)whitelist blacklist:(NSArray *)blacklist 2671 injectionTime:(WebUserScriptInjectionTime)injectionTime 2672{ 2673 [WebView _addUserScriptToGroup:groupName world:world source:source url:url whitelist:whitelist blacklist:blacklist injectionTime:injectionTime injectedFrames:WebInjectInAllFrames]; 2674} 2675 2676+ (void)_addUserScriptToGroup:(NSString *)groupName world:(WebScriptWorld *)world source:(NSString *)source url:(NSURL *)url 2677 whitelist:(NSArray *)whitelist blacklist:(NSArray *)blacklist 2678 injectionTime:(WebUserScriptInjectionTime)injectionTime 2679 injectedFrames:(WebUserContentInjectedFrames)injectedFrames 2680{ 2681 String group(groupName); 2682 if (group.isEmpty()) 2683 return; 2684 2685 PageGroup* pageGroup = PageGroup::pageGroup(group); 2686 if (!pageGroup) 2687 return; 2688 2689 pageGroup->addUserScriptToWorld(core(world), source, url, toStringVector(whitelist), toStringVector(blacklist), 2690 injectionTime == WebInjectAtDocumentStart ? InjectAtDocumentStart : InjectAtDocumentEnd, 2691 injectedFrames == WebInjectInAllFrames ? InjectInAllFrames : InjectInTopFrameOnly); 2692} 2693 2694+ (void)_addUserStyleSheetToGroup:(NSString *)groupName world:(WebScriptWorld *)world source:(NSString *)source url:(NSURL *)url 2695 whitelist:(NSArray *)whitelist blacklist:(NSArray *)blacklist 2696{ 2697 [WebView _addUserStyleSheetToGroup:groupName world:world source:source url:url whitelist:whitelist blacklist:blacklist injectedFrames:WebInjectInAllFrames]; 2698} 2699 2700+ (void)_addUserStyleSheetToGroup:(NSString *)groupName world:(WebScriptWorld *)world source:(NSString *)source url:(NSURL *)url 2701 whitelist:(NSArray *)whitelist blacklist:(NSArray *)blacklist 2702 injectedFrames:(WebUserContentInjectedFrames)injectedFrames 2703{ 2704 String group(groupName); 2705 if (group.isEmpty()) 2706 return; 2707 2708 PageGroup* pageGroup = PageGroup::pageGroup(group); 2709 if (!pageGroup) 2710 return; 2711 2712 pageGroup->addUserStyleSheetToWorld(core(world), source, url, toStringVector(whitelist), toStringVector(blacklist), injectedFrames == WebInjectInAllFrames ? InjectInAllFrames : InjectInTopFrameOnly); 2713} 2714 2715+ (void)_removeUserScriptFromGroup:(NSString *)groupName world:(WebScriptWorld *)world url:(NSURL *)url 2716{ 2717 String group(groupName); 2718 if (group.isEmpty()) 2719 return; 2720 2721 PageGroup* pageGroup = PageGroup::pageGroup(group); 2722 if (!pageGroup) 2723 return; 2724 2725 pageGroup->removeUserScriptFromWorld(core(world), url); 2726} 2727 2728+ (void)_removeUserStyleSheetFromGroup:(NSString *)groupName world:(WebScriptWorld *)world url:(NSURL *)url 2729{ 2730 String group(groupName); 2731 if (group.isEmpty()) 2732 return; 2733 2734 PageGroup* pageGroup = PageGroup::pageGroup(group); 2735 if (!pageGroup) 2736 return; 2737 2738 pageGroup->removeUserStyleSheetFromWorld(core(world), url); 2739} 2740 2741+ (void)_removeUserScriptsFromGroup:(NSString *)groupName world:(WebScriptWorld *)world 2742{ 2743 String group(groupName); 2744 if (group.isEmpty()) 2745 return; 2746 2747 PageGroup* pageGroup = PageGroup::pageGroup(group); 2748 if (!pageGroup) 2749 return; 2750 2751 pageGroup->removeUserScriptsFromWorld(core(world)); 2752} 2753 2754+ (void)_removeUserStyleSheetsFromGroup:(NSString *)groupName world:(WebScriptWorld *)world 2755{ 2756 String group(groupName); 2757 if (group.isEmpty()) 2758 return; 2759 2760 PageGroup* pageGroup = PageGroup::pageGroup(group); 2761 if (!pageGroup) 2762 return; 2763 2764 pageGroup->removeUserStyleSheetsFromWorld(core(world)); 2765} 2766 2767+ (void)_removeAllUserContentFromGroup:(NSString *)groupName 2768{ 2769 String group(groupName); 2770 if (group.isEmpty()) 2771 return; 2772 2773 PageGroup* pageGroup = PageGroup::pageGroup(group); 2774 if (!pageGroup) 2775 return; 2776 2777 pageGroup->removeAllUserContent(); 2778} 2779 2780- (BOOL)cssAnimationsSuspended 2781{ 2782 // should ask the page! 2783 Frame* frame = core([self mainFrame]); 2784 if (frame) 2785 return frame->animation()->isSuspended(); 2786 2787 return false; 2788} 2789 2790- (void)setCSSAnimationsSuspended:(BOOL)suspended 2791{ 2792 Frame* frame = core([self mainFrame]); 2793 if (suspended == frame->animation()->isSuspended()) 2794 return; 2795 2796 if (suspended) 2797 frame->animation()->suspendAnimations(); 2798 else 2799 frame->animation()->resumeAnimations(); 2800} 2801 2802+ (void)_setDomainRelaxationForbidden:(BOOL)forbidden forURLScheme:(NSString *)scheme 2803{ 2804 SchemeRegistry::setDomainRelaxationForbiddenForURLScheme(forbidden, scheme); 2805} 2806 2807+ (void)_registerURLSchemeAsSecure:(NSString *)scheme 2808{ 2809 SchemeRegistry::registerURLSchemeAsSecure(scheme); 2810} 2811 2812+ (void)_registerURLSchemeAsAllowingLocalStorageAccessInPrivateBrowsing:(NSString *)scheme 2813{ 2814 SchemeRegistry::registerURLSchemeAsAllowingLocalStorageAccessInPrivateBrowsing(scheme); 2815} 2816 2817+ (void)_registerURLSchemeAsAllowingDatabaseAccessInPrivateBrowsing:(NSString *)scheme 2818{ 2819 SchemeRegistry::registerURLSchemeAsAllowingDatabaseAccessInPrivateBrowsing(scheme); 2820} 2821 2822- (void)_scaleWebView:(float)scale atOrigin:(NSPoint)origin 2823{ 2824 _private->page->setPageScaleFactor(scale, IntPoint(origin)); 2825} 2826 2827- (float)_viewScaleFactor 2828{ 2829 return _private->page->pageScaleFactor(); 2830} 2831 2832- (void)_setUseFixedLayout:(BOOL)fixed 2833{ 2834 Frame* coreFrame = [self _mainCoreFrame]; 2835 if (!coreFrame) 2836 return; 2837 2838 FrameView* view = coreFrame->view(); 2839 if (!view) 2840 return; 2841 2842 view->setUseFixedLayout(fixed); 2843 if (!fixed) 2844 view->setFixedLayoutSize(IntSize()); 2845} 2846 2847- (void)_setFixedLayoutSize:(NSSize)size 2848{ 2849 Frame* coreFrame = [self _mainCoreFrame]; 2850 if (!coreFrame) 2851 return; 2852 2853 FrameView* view = coreFrame->view(); 2854 if (!view) 2855 return; 2856 2857 view->setFixedLayoutSize(IntSize(size)); 2858 view->forceLayout(); 2859} 2860 2861- (BOOL)_useFixedLayout 2862{ 2863 Frame* coreFrame = [self _mainCoreFrame]; 2864 if (!coreFrame) 2865 return NO; 2866 2867 FrameView* view = coreFrame->view(); 2868 if (!view) 2869 return NO; 2870 2871 return view->useFixedLayout(); 2872} 2873 2874- (NSSize)_fixedLayoutSize 2875{ 2876 Frame* coreFrame = [self _mainCoreFrame]; 2877 if (!coreFrame) 2878 return IntSize(); 2879 2880 FrameView* view = coreFrame->view(); 2881 if (!view) 2882 return IntSize(); 2883 2884 return view->fixedLayoutSize(); 2885} 2886 2887- (void)_setPaginationMode:(WebPaginationMode)paginationMode 2888{ 2889 Page* page = core(self); 2890 if (!page) 2891 return; 2892 2893 Pagination pagination = page->pagination(); 2894 switch (paginationMode) { 2895 case WebPaginationModeUnpaginated: 2896 pagination.mode = Pagination::Unpaginated; 2897 break; 2898 case WebPaginationModeLeftToRight: 2899 pagination.mode = Pagination::LeftToRightPaginated; 2900 break; 2901 case WebPaginationModeRightToLeft: 2902 pagination.mode = Pagination::RightToLeftPaginated; 2903 break; 2904 case WebPaginationModeTopToBottom: 2905 pagination.mode = Pagination::TopToBottomPaginated; 2906 break; 2907 case WebPaginationModeBottomToTop: 2908 pagination.mode = Pagination::BottomToTopPaginated; 2909 break; 2910 default: 2911 return; 2912 } 2913 2914 page->setPagination(pagination); 2915} 2916 2917- (WebPaginationMode)_paginationMode 2918{ 2919 Page* page = core(self); 2920 if (!page) 2921 return WebPaginationModeUnpaginated; 2922 2923 switch (page->pagination().mode) { 2924 case Pagination::Unpaginated: 2925 return WebPaginationModeUnpaginated; 2926 case Pagination::LeftToRightPaginated: 2927 return WebPaginationModeLeftToRight; 2928 case Pagination::RightToLeftPaginated: 2929 return WebPaginationModeRightToLeft; 2930 case Pagination::TopToBottomPaginated: 2931 return WebPaginationModeTopToBottom; 2932 case Pagination::BottomToTopPaginated: 2933 return WebPaginationModeBottomToTop; 2934 } 2935 2936 ASSERT_NOT_REACHED(); 2937 return WebPaginationModeUnpaginated; 2938} 2939 2940- (void)_listenForLayoutMilestones:(WebLayoutMilestones)layoutMilestones 2941{ 2942 Page* page = core(self); 2943 if (!page) 2944 return; 2945 2946 page->addLayoutMilestones(coreLayoutMilestones(layoutMilestones)); 2947} 2948 2949- (WebLayoutMilestones)_layoutMilestones 2950{ 2951 Page* page = core(self); 2952 if (!page) 2953 return 0; 2954 2955 return kitLayoutMilestones(page->requestedLayoutMilestones()); 2956} 2957 2958- (void)_setVisibilityState:(WebPageVisibilityState)visibilityState isInitialState:(BOOL)isInitialState 2959{ 2960#if ENABLE(PAGE_VISIBILITY_API) || ENABLE(HIDDEN_PAGE_DOM_TIMER_THROTTLING) 2961 if (_private->page) 2962 _private->page->setVisibilityState(core(visibilityState), isInitialState); 2963#endif 2964} 2965 2966- (void)_setPaginationBehavesLikeColumns:(BOOL)behavesLikeColumns 2967{ 2968 Page* page = core(self); 2969 if (!page) 2970 return; 2971 2972 Pagination pagination = page->pagination(); 2973 pagination.behavesLikeColumns = behavesLikeColumns; 2974 2975 page->setPagination(pagination); 2976} 2977 2978- (BOOL)_paginationBehavesLikeColumns 2979{ 2980 Page* page = core(self); 2981 if (!page) 2982 return NO; 2983 2984 return page->pagination().behavesLikeColumns; 2985} 2986 2987- (void)_setPageLength:(CGFloat)pageLength 2988{ 2989 Page* page = core(self); 2990 if (!page) 2991 return; 2992 2993 Pagination pagination = page->pagination(); 2994 pagination.pageLength = pageLength; 2995 2996 page->setPagination(pagination); 2997} 2998 2999- (CGFloat)_pageLength 3000{ 3001 Page* page = core(self); 3002 if (!page) 3003 return 1; 3004 3005 return page->pagination().pageLength; 3006} 3007 3008- (void)_setGapBetweenPages:(CGFloat)pageGap 3009{ 3010 Page* page = core(self); 3011 if (!page) 3012 return; 3013 3014 Pagination pagination = page->pagination(); 3015 pagination.gap = pageGap; 3016 page->setPagination(pagination); 3017} 3018 3019- (CGFloat)_gapBetweenPages 3020{ 3021 Page* page = core(self); 3022 if (!page) 3023 return 0; 3024 3025 return page->pagination().gap; 3026} 3027 3028- (NSUInteger)_pageCount 3029{ 3030 Page* page = core(self); 3031 if (!page) 3032 return 0; 3033 3034 return page->pageCount(); 3035} 3036 3037- (CGFloat)_backingScaleFactor 3038{ 3039 return [self _deviceScaleFactor]; 3040} 3041 3042- (void)_setCustomBackingScaleFactor:(CGFloat)customScaleFactor 3043{ 3044 float oldScaleFactor = [self _deviceScaleFactor]; 3045 3046 _private->customDeviceScaleFactor = customScaleFactor; 3047 3048 if (oldScaleFactor != [self _deviceScaleFactor]) 3049 _private->page->setDeviceScaleFactor([self _deviceScaleFactor]); 3050} 3051 3052- (NSUInteger)markAllMatchesForText:(NSString *)string caseSensitive:(BOOL)caseFlag highlight:(BOOL)highlight limit:(NSUInteger)limit 3053{ 3054 return [self countMatchesForText:string options:(caseFlag ? 0 : WebFindOptionsCaseInsensitive) highlight:highlight limit:limit markMatches:YES]; 3055} 3056 3057- (NSUInteger)countMatchesForText:(NSString *)string caseSensitive:(BOOL)caseFlag highlight:(BOOL)highlight limit:(NSUInteger)limit markMatches:(BOOL)markMatches 3058{ 3059 return [self countMatchesForText:string options:(caseFlag ? 0 : WebFindOptionsCaseInsensitive) highlight:highlight limit:limit markMatches:markMatches]; 3060} 3061 3062- (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag startInSelection:(BOOL)startInSelection 3063{ 3064 return [self findString:string options:((forward ? 0 : WebFindOptionsBackwards) | (caseFlag ? 0 : WebFindOptionsCaseInsensitive) | (wrapFlag ? WebFindOptionsWrapAround : 0) | (startInSelection ? WebFindOptionsStartInSelection : 0))]; 3065} 3066 3067+ (void)_setLoadResourcesSerially:(BOOL)serialize 3068{ 3069 WebPlatformStrategies::initializeIfNecessary(); 3070 resourceLoadScheduler()->setSerialLoadingEnabled(serialize); 3071} 3072 3073+ (BOOL)_HTTPPipeliningEnabled 3074{ 3075 return ResourceRequest::httpPipeliningEnabled(); 3076} 3077 3078+ (void)_setHTTPPipeliningEnabled:(BOOL)enabled 3079{ 3080 ResourceRequest::setHTTPPipeliningEnabled(enabled); 3081} 3082 3083- (void)_setSourceApplicationAuditData:(NSData *)sourceApplicationAuditData 3084{ 3085 if (_private->sourceApplicationAuditData == sourceApplicationAuditData) 3086 return; 3087 3088 _private->sourceApplicationAuditData = adoptNS([sourceApplicationAuditData copy]); 3089} 3090 3091- (NSData *)_sourceApplicationAuditData 3092{ 3093 return _private->sourceApplicationAuditData.get(); 3094} 3095 3096@end 3097 3098@implementation _WebSafeForwarder 3099 3100// Used to send messages to delegates that implement informal protocols. 3101 3102- (id)initWithTarget:(id)t defaultTarget:(id)dt 3103{ 3104 self = [super init]; 3105 if (!self) 3106 return nil; 3107 target = t; // Non retained. 3108 defaultTarget = dt; 3109 return self; 3110} 3111 3112- (void)forwardInvocation:(NSInvocation *)invocation 3113{ 3114 if ([target respondsToSelector:[invocation selector]]) { 3115 @try { 3116 [invocation invokeWithTarget:target]; 3117 } @catch(id exception) { 3118 ReportDiscardedDelegateException([invocation selector], exception); 3119 } 3120 return; 3121 } 3122 3123 if ([defaultTarget respondsToSelector:[invocation selector]]) 3124 [invocation invokeWithTarget:defaultTarget]; 3125 3126 // Do nothing quietly if method not implemented. 3127} 3128 3129- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector 3130{ 3131 return [defaultTarget methodSignatureForSelector:aSelector]; 3132} 3133 3134@end 3135 3136@implementation WebView 3137 3138+ (void)initialize 3139{ 3140 static BOOL initialized = NO; 3141 if (initialized) 3142 return; 3143 initialized = YES; 3144 3145 InitWebCoreSystemInterface(); 3146 JSC::initializeThreading(); 3147 WTF::initializeMainThreadToProcessMainThread(); 3148 WebCore::RunLoop::initializeMainRunLoop(); 3149 3150 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_applicationWillTerminate) name:NSApplicationWillTerminateNotification object:NSApp]; 3151 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_cacheModelChangedNotification:) name:WebPreferencesCacheModelChangedInternalNotification object:nil]; 3152 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesRemovedNotification:) name:WebPreferencesRemovedNotification object:nil]; 3153 3154 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 3155 3156#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 3157 [defaults registerDefaults:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:WebKitKerningAndLigaturesEnabledByDefaultDefaultsKey]]; 3158#endif 3159 3160 continuousSpellCheckingEnabled = [defaults boolForKey:WebContinuousSpellCheckingEnabled]; 3161 grammarCheckingEnabled = [defaults boolForKey:WebGrammarCheckingEnabled]; 3162 3163 Font::setDefaultTypesettingFeatures([defaults boolForKey:WebKitKerningAndLigaturesEnabledByDefaultDefaultsKey] ? Kerning | Ligatures : 0); 3164 3165 automaticQuoteSubstitutionEnabled = [self _shouldAutomaticQuoteSubstitutionBeEnabled]; 3166 automaticLinkDetectionEnabled = [defaults boolForKey:WebAutomaticLinkDetectionEnabled]; 3167 automaticDashSubstitutionEnabled = [self _shouldAutomaticDashSubstitutionBeEnabled]; 3168 automaticTextReplacementEnabled = [self _shouldAutomaticTextReplacementBeEnabled]; 3169 automaticSpellingCorrectionEnabled = [self _shouldAutomaticSpellingCorrectionBeEnabled]; 3170 3171 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_didChangeAutomaticTextReplacementEnabled:) 3172 name:NSSpellCheckerDidChangeAutomaticTextReplacementNotification object:nil]; 3173 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_didChangeAutomaticSpellingCorrectionEnabled:) 3174 name:NSSpellCheckerDidChangeAutomaticSpellingCorrectionNotification object:nil]; 3175 3176#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 3177 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_didChangeAutomaticQuoteSubstitutionEnabled:) 3178 name:NSSpellCheckerDidChangeAutomaticQuoteSubstitutionNotification object:nil]; 3179 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_didChangeAutomaticDashSubstitutionEnabled:) 3180 name:NSSpellCheckerDidChangeAutomaticDashSubstitutionNotification object:nil]; 3181#endif 3182} 3183 3184+ (BOOL)_shouldAutomaticTextReplacementBeEnabled 3185{ 3186 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 3187 if (![defaults objectForKey:WebAutomaticTextReplacementEnabled]) 3188 return [NSSpellChecker isAutomaticTextReplacementEnabled]; 3189 return [defaults boolForKey:WebAutomaticTextReplacementEnabled]; 3190} 3191 3192+ (void)_didChangeAutomaticTextReplacementEnabled:(NSNotification *)notification 3193{ 3194 automaticTextReplacementEnabled = [self _shouldAutomaticTextReplacementBeEnabled]; 3195 [[NSSpellChecker sharedSpellChecker] updatePanels]; 3196} 3197 3198+ (BOOL)_shouldAutomaticSpellingCorrectionBeEnabled 3199{ 3200 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 3201 if (![defaults objectForKey:WebAutomaticSpellingCorrectionEnabled]) 3202 return [NSSpellChecker isAutomaticTextReplacementEnabled]; 3203 return [defaults boolForKey:WebAutomaticSpellingCorrectionEnabled]; 3204} 3205 3206+ (void)_didChangeAutomaticSpellingCorrectionEnabled:(NSNotification *)notification 3207{ 3208 automaticSpellingCorrectionEnabled = [self _shouldAutomaticSpellingCorrectionBeEnabled]; 3209 [[NSSpellChecker sharedSpellChecker] updatePanels]; 3210} 3211 3212+ (BOOL)_shouldAutomaticQuoteSubstitutionBeEnabled 3213{ 3214 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 3215#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 3216 if (![defaults objectForKey:WebAutomaticQuoteSubstitutionEnabled]) 3217 return [NSSpellChecker isAutomaticQuoteSubstitutionEnabled]; 3218#endif 3219 return [defaults boolForKey:WebAutomaticQuoteSubstitutionEnabled]; 3220} 3221 3222+ (BOOL)_shouldAutomaticDashSubstitutionBeEnabled 3223{ 3224 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 3225#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 3226 if (![defaults objectForKey:WebAutomaticDashSubstitutionEnabled]) 3227 return [NSSpellChecker isAutomaticDashSubstitutionEnabled]; 3228#endif 3229 return [defaults boolForKey:WebAutomaticDashSubstitutionEnabled]; 3230} 3231 3232#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 3233+ (void)_didChangeAutomaticQuoteSubstitutionEnabled:(NSNotification *)notification 3234{ 3235 automaticQuoteSubstitutionEnabled = [self _shouldAutomaticQuoteSubstitutionBeEnabled]; 3236 [[NSSpellChecker sharedSpellChecker] updatePanels]; 3237} 3238 3239+ (void)_didChangeAutomaticDashSubstitutionEnabled:(NSNotification *)notification 3240{ 3241 automaticDashSubstitutionEnabled = [self _shouldAutomaticDashSubstitutionBeEnabled]; 3242 [[NSSpellChecker sharedSpellChecker] updatePanels]; 3243} 3244#endif 3245 3246+ (void)_applicationWillTerminate 3247{ 3248 applicationIsTerminating = YES; 3249 3250 if (fastDocumentTeardownEnabled()) 3251 [self closeAllWebViews]; 3252 3253 if (!pluginDatabaseClientCount) 3254 [WebPluginDatabase closeSharedDatabase]; 3255 3256 PageGroup::closeLocalStorage(); 3257} 3258 3259+ (BOOL)_canShowMIMEType:(NSString *)MIMEType allowingPlugins:(BOOL)allowPlugins 3260{ 3261 return [self _viewClass:nil andRepresentationClass:nil forMIMEType:MIMEType allowingPlugins:allowPlugins]; 3262} 3263 3264+ (BOOL)canShowMIMEType:(NSString *)MIMEType 3265{ 3266 return [self _canShowMIMEType:MIMEType allowingPlugins:YES]; 3267} 3268 3269- (BOOL)_canShowMIMEType:(NSString *)MIMEType 3270{ 3271 return [[self class] _canShowMIMEType:MIMEType allowingPlugins:[_private->preferences arePlugInsEnabled]]; 3272} 3273 3274- (WebBasePluginPackage *)_pluginForMIMEType:(NSString *)MIMEType 3275{ 3276 if (![_private->preferences arePlugInsEnabled]) 3277 return nil; 3278 3279 WebBasePluginPackage *pluginPackage = [[WebPluginDatabase sharedDatabase] pluginForMIMEType:MIMEType]; 3280 if (pluginPackage) 3281 return pluginPackage; 3282 3283 if (_private->pluginDatabase) 3284 return [_private->pluginDatabase pluginForMIMEType:MIMEType]; 3285 3286 return nil; 3287} 3288 3289#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) 3290- (WebBasePluginPackage *)_videoProxyPluginForMIMEType:(NSString *)MIMEType 3291{ 3292 WebBasePluginPackage *pluginPackage = [[WebPluginDatabase sharedDatabase] pluginForMIMEType:MIMEType]; 3293 if (pluginPackage) 3294 return pluginPackage; 3295 3296 if (_private->pluginDatabase) 3297 return [_private->pluginDatabase pluginForMIMEType:MIMEType]; 3298 3299 return nil; 3300} 3301#endif 3302 3303- (WebBasePluginPackage *)_pluginForExtension:(NSString *)extension 3304{ 3305 if (![_private->preferences arePlugInsEnabled]) 3306 return nil; 3307 3308 WebBasePluginPackage *pluginPackage = [[WebPluginDatabase sharedDatabase] pluginForExtension:extension]; 3309 if (pluginPackage) 3310 return pluginPackage; 3311 3312 if (_private->pluginDatabase) 3313 return [_private->pluginDatabase pluginForExtension:extension]; 3314 3315 return nil; 3316} 3317 3318- (void)addPluginInstanceView:(NSView *)view 3319{ 3320 if (!_private->pluginDatabase) 3321 _private->pluginDatabase = [[WebPluginDatabase alloc] init]; 3322 [_private->pluginDatabase addPluginInstanceView:view]; 3323} 3324 3325- (void)removePluginInstanceView:(NSView *)view 3326{ 3327 if (_private->pluginDatabase) 3328 [_private->pluginDatabase removePluginInstanceView:view]; 3329} 3330 3331- (void)removePluginInstanceViewsFor:(WebFrame*)webFrame 3332{ 3333 if (_private->pluginDatabase) 3334 [_private->pluginDatabase removePluginInstanceViewsFor:webFrame]; 3335} 3336 3337- (BOOL)_isMIMETypeRegisteredAsPlugin:(NSString *)MIMEType 3338{ 3339 if (![_private->preferences arePlugInsEnabled]) 3340 return NO; 3341 3342 if ([[WebPluginDatabase sharedDatabase] isMIMETypeRegistered:MIMEType]) 3343 return YES; 3344 3345 if (_private->pluginDatabase && [_private->pluginDatabase isMIMETypeRegistered:MIMEType]) 3346 return YES; 3347 3348 return NO; 3349} 3350 3351+ (BOOL)canShowMIMETypeAsHTML:(NSString *)MIMEType 3352{ 3353 return [WebFrameView _canShowMIMETypeAsHTML:MIMEType]; 3354} 3355 3356+ (NSArray *)MIMETypesShownAsHTML 3357{ 3358 NSMutableDictionary *viewTypes = [WebFrameView _viewTypesAllowImageTypeOmission:YES]; 3359 NSEnumerator *enumerator = [viewTypes keyEnumerator]; 3360 id key; 3361 NSMutableArray *array = [[[NSMutableArray alloc] init] autorelease]; 3362 3363 while ((key = [enumerator nextObject])) { 3364 if ([viewTypes objectForKey:key] == [WebHTMLView class]) 3365 [array addObject:key]; 3366 } 3367 3368 return array; 3369} 3370 3371+ (void)setMIMETypesShownAsHTML:(NSArray *)MIMETypes 3372{ 3373 NSDictionary *viewTypes = [[WebFrameView _viewTypesAllowImageTypeOmission:YES] copy]; 3374 NSEnumerator *enumerator = [viewTypes keyEnumerator]; 3375 id key; 3376 while ((key = [enumerator nextObject])) { 3377 if ([viewTypes objectForKey:key] == [WebHTMLView class]) 3378 [WebView _unregisterViewClassAndRepresentationClassForMIMEType:key]; 3379 } 3380 3381 int i, count = [MIMETypes count]; 3382 for (i = 0; i < count; i++) { 3383 [WebView registerViewClass:[WebHTMLView class] 3384 representationClass:[WebHTMLRepresentation class] 3385 forMIMEType:[MIMETypes objectAtIndex:i]]; 3386 } 3387 [viewTypes release]; 3388} 3389 3390+ (NSURL *)URLFromPasteboard:(NSPasteboard *)pasteboard 3391{ 3392 return [pasteboard _web_bestURL]; 3393} 3394 3395+ (NSString *)URLTitleFromPasteboard:(NSPasteboard *)pasteboard 3396{ 3397 return [pasteboard stringForType:WebURLNamePboardType]; 3398} 3399 3400+ (void)registerURLSchemeAsLocal:(NSString *)protocol 3401{ 3402 SchemeRegistry::registerURLSchemeAsLocal(protocol); 3403} 3404 3405- (id)_initWithArguments:(NSDictionary *) arguments 3406{ 3407 NSCoder *decoder = [arguments objectForKey:@"decoder"]; 3408 if (decoder) { 3409 self = [self initWithCoder:decoder]; 3410 } else { 3411 ASSERT([arguments objectForKey:@"frame"]); 3412 NSValue *frameValue = [arguments objectForKey:@"frame"]; 3413 NSRect frame = (frameValue ? [frameValue rectValue] : NSZeroRect); 3414 NSString *frameName = [arguments objectForKey:@"frameName"]; 3415 NSString *groupName = [arguments objectForKey:@"groupName"]; 3416 self = [self initWithFrame:frame frameName:frameName groupName:groupName]; 3417 } 3418 3419 return self; 3420} 3421 3422static bool clientNeedsWebViewInitThreadWorkaround() 3423{ 3424 if (WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_WEBVIEW_INIT_THREAD_WORKAROUND)) 3425 return false; 3426 3427 NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier]; 3428 3429 // Installer. 3430 if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.installer"]) 3431 return true; 3432 3433 // Automator. 3434 if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.Automator"]) 3435 return true; 3436 3437 // Automator Runner. 3438 if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.AutomatorRunner"]) 3439 return true; 3440 3441 // Automator workflows. 3442 if ([bundleIdentifier _webkit_hasCaseInsensitivePrefix:@"com.apple.Automator."]) 3443 return true; 3444 3445 return false; 3446} 3447 3448static bool needsWebViewInitThreadWorkaround() 3449{ 3450 static bool isOldClient = clientNeedsWebViewInitThreadWorkaround(); 3451 return isOldClient && !pthread_main_np(); 3452} 3453 3454- (id)initWithFrame:(NSRect)f 3455{ 3456 return [self initWithFrame:f frameName:nil groupName:nil]; 3457} 3458 3459- (id)initWithFrame:(NSRect)f frameName:(NSString *)frameName groupName:(NSString *)groupName 3460{ 3461 if (needsWebViewInitThreadWorkaround()) 3462 return [[self _webkit_invokeOnMainThread] initWithFrame:f frameName:frameName groupName:groupName]; 3463 3464 WebCoreThreadViolationCheckRoundTwo(); 3465 return [self _initWithFrame:f frameName:frameName groupName:groupName usesDocumentViews:YES]; 3466} 3467 3468- (id)initWithCoder:(NSCoder *)decoder 3469{ 3470 if (needsWebViewInitThreadWorkaround()) 3471 return [[self _webkit_invokeOnMainThread] initWithCoder:decoder]; 3472 3473 WebCoreThreadViolationCheckRoundTwo(); 3474 WebView *result = nil; 3475 3476 @try { 3477 NSString *frameName; 3478 NSString *groupName; 3479 WebPreferences *preferences; 3480 BOOL useBackForwardList = NO; 3481 BOOL allowsUndo = YES; 3482 3483 result = [super initWithCoder:decoder]; 3484 result->_private = [[WebViewPrivate alloc] init]; 3485 3486 // We don't want any of the archived subviews. The subviews will always 3487 // be created in _commonInitializationFrameName:groupName:. 3488 [[result subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)]; 3489 3490 if ([decoder allowsKeyedCoding]) { 3491 frameName = [decoder decodeObjectForKey:@"FrameName"]; 3492 groupName = [decoder decodeObjectForKey:@"GroupName"]; 3493 preferences = [decoder decodeObjectForKey:@"Preferences"]; 3494 useBackForwardList = [decoder decodeBoolForKey:@"UseBackForwardList"]; 3495 if ([decoder containsValueForKey:@"AllowsUndo"]) 3496 allowsUndo = [decoder decodeBoolForKey:@"AllowsUndo"]; 3497 } else { 3498 int version; 3499 [decoder decodeValueOfObjCType:@encode(int) at:&version]; 3500 frameName = [decoder decodeObject]; 3501 groupName = [decoder decodeObject]; 3502 preferences = [decoder decodeObject]; 3503 if (version > 1) 3504 [decoder decodeValuesOfObjCTypes:"c", &useBackForwardList]; 3505 // The allowsUndo field is no longer written out in encodeWithCoder, but since there are 3506 // version 3 NIBs that have this field encoded, we still need to read it in. 3507 if (version == 3) 3508 [decoder decodeValuesOfObjCTypes:"c", &allowsUndo]; 3509 } 3510 3511 if (![frameName isKindOfClass:[NSString class]]) 3512 frameName = nil; 3513 if (![groupName isKindOfClass:[NSString class]]) 3514 groupName = nil; 3515 if (![preferences isKindOfClass:[WebPreferences class]]) 3516 preferences = nil; 3517 3518 LOG(Encoding, "FrameName = %@, GroupName = %@, useBackForwardList = %d\n", frameName, groupName, (int)useBackForwardList); 3519 [result _commonInitializationWithFrameName:frameName groupName:groupName]; 3520 static_cast<BackForwardListImpl*>([result page]->backForwardList())->setEnabled(useBackForwardList); 3521 result->_private->allowsUndo = allowsUndo; 3522 if (preferences) 3523 [result setPreferences:preferences]; 3524 } @catch (NSException *localException) { 3525 result = nil; 3526 [self release]; 3527 } 3528 3529 return result; 3530} 3531 3532- (void)encodeWithCoder:(NSCoder *)encoder 3533{ 3534 // Set asside the subviews before we archive. We don't want to archive any subviews. 3535 // The subviews will always be created in _commonInitializationFrameName:groupName:. 3536 id originalSubviews = _subviews; 3537 _subviews = nil; 3538 3539 [super encodeWithCoder:encoder]; 3540 3541 // Restore the subviews we set aside. 3542 _subviews = originalSubviews; 3543 3544 BOOL useBackForwardList = _private->page && static_cast<BackForwardListImpl*>(_private->page->backForwardList())->enabled(); 3545 if ([encoder allowsKeyedCoding]) { 3546 [encoder encodeObject:[[self mainFrame] name] forKey:@"FrameName"]; 3547 [encoder encodeObject:[self groupName] forKey:@"GroupName"]; 3548 [encoder encodeObject:[self preferences] forKey:@"Preferences"]; 3549 [encoder encodeBool:useBackForwardList forKey:@"UseBackForwardList"]; 3550 [encoder encodeBool:_private->allowsUndo forKey:@"AllowsUndo"]; 3551 } else { 3552 int version = WebViewVersion; 3553 [encoder encodeValueOfObjCType:@encode(int) at:&version]; 3554 [encoder encodeObject:[[self mainFrame] name]]; 3555 [encoder encodeObject:[self groupName]]; 3556 [encoder encodeObject:[self preferences]]; 3557 [encoder encodeValuesOfObjCTypes:"c", &useBackForwardList]; 3558 // DO NOT encode any new fields here, doing so will break older WebKit releases. 3559 } 3560 3561 LOG(Encoding, "FrameName = %@, GroupName = %@, useBackForwardList = %d\n", [[self mainFrame] name], [self groupName], (int)useBackForwardList); 3562} 3563 3564- (void)dealloc 3565{ 3566 if (WebCoreObjCScheduleDeallocateOnMainThread([WebView class], self)) 3567 return; 3568 3569 // call close to ensure we tear-down completely 3570 // this maintains our old behavior for existing applications 3571 [self close]; 3572 3573 if ([[self class] shouldIncludeInWebKitStatistics]) 3574 --WebViewCount; 3575 3576 if ([self _needsFrameLoadDelegateRetainQuirk]) 3577 [_private->frameLoadDelegate release]; 3578 3579 [_private release]; 3580 // [super dealloc] can end up dispatching against _private (3466082) 3581 _private = nil; 3582 3583 [super dealloc]; 3584} 3585 3586- (void)finalize 3587{ 3588 ASSERT(_private->closed); 3589 3590 --WebViewCount; 3591 3592 [super finalize]; 3593} 3594 3595- (void)close 3596{ 3597 // _close existed first, and some clients might be calling or overriding it, so call through. 3598 [self _close]; 3599} 3600 3601- (void)setShouldCloseWithWindow:(BOOL)close 3602{ 3603 _private->shouldCloseWithWindow = close; 3604} 3605 3606- (BOOL)shouldCloseWithWindow 3607{ 3608 return _private->shouldCloseWithWindow; 3609} 3610 3611// FIXME: Use AppKit constants for these when they are available. 3612static NSString * const windowDidChangeBackingPropertiesNotification = @"NSWindowDidChangeBackingPropertiesNotification"; 3613static NSString * const backingPropertyOldScaleFactorKey = @"NSBackingPropertyOldScaleFactorKey"; 3614 3615- (void)addWindowObserversForWindow:(NSWindow *)window 3616{ 3617 if (window) { 3618 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillOrderOnScreen:) 3619 name:WKWindowWillOrderOnScreenNotification() object:window]; 3620 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillOrderOffScreen:) 3621 name:WKWindowWillOrderOffScreenNotification() object:window]; 3622 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowDidChangeBackingProperties:) 3623 name:windowDidChangeBackingPropertiesNotification object:window]; 3624 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowDidChangeScreen:) 3625 name:NSWindowDidChangeScreenNotification object:window]; 3626 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowVisibilityChanged:) 3627 name:NSWindowDidMiniaturizeNotification object:window]; 3628 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowVisibilityChanged:) 3629 name:NSWindowDidDeminiaturizeNotification object:window]; 3630 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowVisibilityChanged:) 3631 name:@"NSWindowDidOrderOffScreenNotification" object:window]; 3632 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowVisibilityChanged:) 3633 name:@"_NSWindowDidBecomeVisible" object:window]; 3634 } 3635} 3636 3637- (void)removeWindowObservers 3638{ 3639 NSWindow *window = [self window]; 3640 if (window) { 3641 [[NSNotificationCenter defaultCenter] removeObserver:self 3642 name:WKWindowWillOrderOnScreenNotification() object:window]; 3643 [[NSNotificationCenter defaultCenter] removeObserver:self 3644 name:WKWindowWillOrderOffScreenNotification() object:window]; 3645 [[NSNotificationCenter defaultCenter] removeObserver:self 3646 name:windowDidChangeBackingPropertiesNotification object:window]; 3647 [[NSNotificationCenter defaultCenter] removeObserver:self 3648 name:NSWindowDidChangeScreenNotification object:window]; 3649 [[NSNotificationCenter defaultCenter] removeObserver:self 3650 name:NSWindowDidMiniaturizeNotification object:window]; 3651 [[NSNotificationCenter defaultCenter] removeObserver:self 3652 name:NSWindowDidDeminiaturizeNotification object:window]; 3653 [[NSNotificationCenter defaultCenter] removeObserver:self 3654 name:@"NSWindowDidOrderOffScreenNotification" object:window]; 3655 [[NSNotificationCenter defaultCenter] removeObserver:self 3656 name:@"_NSWindowDidBecomeVisible" object:window]; 3657 } 3658} 3659 3660- (void)viewWillMoveToWindow:(NSWindow *)window 3661{ 3662 // Don't do anything if the WebView isn't initialized. 3663 // This happens when decoding a WebView in a nib. 3664 // FIXME: What sets up the observer of NSWindowWillCloseNotification in this case? 3665 if (!_private || _private->closed) 3666 return; 3667 3668 if ([self window] && [self window] != [self hostWindow]) 3669 [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowWillCloseNotification object:[self window]]; 3670 3671 if (window) { 3672 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillClose:) name:NSWindowWillCloseNotification object:window]; 3673 3674 // Ensure that we will receive the events that WebHTMLView (at least) needs. 3675 // The following are expensive enough that we don't want to call them over 3676 // and over, so do them when we move into a window. 3677 [window setAcceptsMouseMovedEvents:YES]; 3678 WKSetNSWindowShouldPostEventNotifications(window, YES); 3679 } else { 3680 _private->page->setCanStartMedia(false); 3681 _private->page->willMoveOffscreen(); 3682 _private->page->setIsInWindow(false); 3683 } 3684 3685 if (window != [self window]) { 3686 [self removeWindowObservers]; 3687 [self addWindowObserversForWindow:window]; 3688 } 3689} 3690 3691- (void)viewDidMoveToWindow 3692{ 3693 // Don't do anything if we aren't initialized. This happens 3694 // when decoding a WebView. When WebViews are decoded their subviews 3695 // are created by initWithCoder: and so won't be normally 3696 // initialized. The stub views are discarded by WebView. 3697 if (!_private || _private->closed) 3698 return; 3699 3700 if ([self window]) { 3701 _private->page->setCanStartMedia(true); 3702 _private->page->didMoveOnscreen(); 3703 _private->page->setIsInWindow(true); 3704 } 3705 3706 _private->page->setDeviceScaleFactor([self _deviceScaleFactor]); 3707 3708 [self _updateActiveState]; 3709 [self _updateVisibilityState]; 3710} 3711 3712- (void)doWindowDidChangeScreen 3713{ 3714 if (_private && _private->page) 3715 _private->page->windowScreenDidChange((PlatformDisplayID)[[[[[self window] screen] deviceDescription] objectForKey:@"NSScreenNumber"] intValue]); 3716} 3717 3718- (void)_windowChangedKeyState 3719{ 3720 [self _updateActiveState]; 3721} 3722 3723- (void)_windowWillOrderOnScreen:(NSNotification *)notification 3724{ 3725 if (![self shouldUpdateWhileOffscreen]) 3726 [self setNeedsDisplay:YES]; 3727 3728 // Send a change screen to make sure the initial displayID is set 3729 [self doWindowDidChangeScreen]; 3730 3731 if (_private && _private->page) { 3732 _private->page->resumeScriptedAnimations(); 3733 _private->page->focusController()->setContainingWindowIsVisible(true); 3734 } 3735} 3736 3737- (void)_windowDidChangeScreen:(NSNotification *)notification 3738{ 3739 [self doWindowDidChangeScreen]; 3740} 3741 3742- (void)_windowWillOrderOffScreen:(NSNotification *)notification 3743{ 3744 if (_private && _private->page) { 3745 _private->page->suspendScriptedAnimations(); 3746 _private->page->focusController()->setContainingWindowIsVisible(false); 3747 } 3748} 3749 3750- (void)_windowVisibilityChanged:(NSNotification *)notification 3751{ 3752 [self _updateVisibilityState]; 3753} 3754 3755- (void)_windowWillClose:(NSNotification *)notification 3756{ 3757 if ([self shouldCloseWithWindow] && ([self window] == [self hostWindow] || ([self window] && ![self hostWindow]) || (![self window] && [self hostWindow]))) 3758 [self close]; 3759} 3760 3761- (void)_windowDidChangeBackingProperties:(NSNotification *)notification 3762{ 3763 CGFloat oldBackingScaleFactor = [[notification.userInfo objectForKey:backingPropertyOldScaleFactorKey] doubleValue]; 3764 CGFloat newBackingScaleFactor = [self _deviceScaleFactor]; 3765 if (oldBackingScaleFactor == newBackingScaleFactor) 3766 return; 3767 3768 _private->page->setDeviceScaleFactor(newBackingScaleFactor); 3769} 3770 3771- (void)setPreferences:(WebPreferences *)prefs 3772{ 3773 if (!prefs) 3774 prefs = [WebPreferences standardPreferences]; 3775 3776 if (_private->preferences == prefs) 3777 return; 3778 3779 [prefs willAddToWebView]; 3780 3781 WebPreferences *oldPrefs = _private->preferences; 3782 3783 [[NSNotificationCenter defaultCenter] removeObserver:self name:WebPreferencesChangedInternalNotification object:[self preferences]]; 3784 [WebPreferences _removeReferenceForIdentifier:[oldPrefs identifier]]; 3785 3786 _private->preferences = [prefs retain]; 3787 3788 // After registering for the notification, post it so the WebCore settings update. 3789 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:) 3790 name:WebPreferencesChangedInternalNotification object:[self preferences]]; 3791 [self _preferencesChanged:[self preferences]]; 3792 [[self preferences] _postPreferencesChangedAPINotification]; 3793 3794 [oldPrefs didRemoveFromWebView]; 3795 [oldPrefs release]; 3796} 3797 3798- (WebPreferences *)preferences 3799{ 3800 return _private->preferences; 3801} 3802 3803- (void)setPreferencesIdentifier:(NSString *)anIdentifier 3804{ 3805 if (!_private->closed && ![anIdentifier isEqual:[[self preferences] identifier]]) { 3806 WebPreferences *prefs = [[WebPreferences alloc] initWithIdentifier:anIdentifier]; 3807 [self setPreferences:prefs]; 3808 [prefs release]; 3809 } 3810} 3811 3812- (NSString *)preferencesIdentifier 3813{ 3814 return [[self preferences] identifier]; 3815} 3816 3817 3818- (void)setUIDelegate:delegate 3819{ 3820 _private->UIDelegate = delegate; 3821 [_private->UIDelegateForwarder release]; 3822 _private->UIDelegateForwarder = nil; 3823} 3824 3825- (id)UIDelegate 3826{ 3827 return _private->UIDelegate; 3828} 3829 3830- (void)setResourceLoadDelegate: delegate 3831{ 3832 _private->resourceProgressDelegate = delegate; 3833 [self _cacheResourceLoadDelegateImplementations]; 3834} 3835 3836- (id)resourceLoadDelegate 3837{ 3838 return _private->resourceProgressDelegate; 3839} 3840 3841- (void)setDownloadDelegate: delegate 3842{ 3843 _private->downloadDelegate = delegate; 3844} 3845 3846 3847- (id)downloadDelegate 3848{ 3849 return _private->downloadDelegate; 3850} 3851 3852- (void)setPolicyDelegate:delegate 3853{ 3854 _private->policyDelegate = delegate; 3855 [_private->policyDelegateForwarder release]; 3856 _private->policyDelegateForwarder = nil; 3857} 3858 3859- (id)policyDelegate 3860{ 3861 return _private->policyDelegate; 3862} 3863 3864- (void)setFrameLoadDelegate:delegate 3865{ 3866 // <rdar://problem/6950660> - Due to some subtle WebKit changes - presumably to delegate callback behavior - we've 3867 // unconvered a latent bug in at least one WebKit app where the delegate wasn't properly retained by the app and 3868 // was dealloc'ed before being cleared. 3869 // This is an effort to keep such apps working for now. 3870 if ([self _needsFrameLoadDelegateRetainQuirk]) { 3871 [delegate retain]; 3872 [_private->frameLoadDelegate release]; 3873 } 3874 3875 _private->frameLoadDelegate = delegate; 3876 [self _cacheFrameLoadDelegateImplementations]; 3877 3878#if ENABLE(ICONDATABASE) 3879 // If this delegate wants callbacks for icons, fire up the icon database. 3880 if (_private->frameLoadDelegateImplementations.didReceiveIconForFrameFunc) 3881 [WebIconDatabase sharedIconDatabase]; 3882#endif 3883} 3884 3885- (id)frameLoadDelegate 3886{ 3887 return _private->frameLoadDelegate; 3888} 3889 3890- (WebFrame *)mainFrame 3891{ 3892 // This can be called in initialization, before _private has been set up (3465613) 3893 if (!_private || !_private->page) 3894 return nil; 3895 return kit(_private->page->mainFrame()); 3896} 3897 3898- (WebFrame *)selectedFrame 3899{ 3900 // If the first responder is a view in our tree, we get the frame containing the first responder. 3901 // This is faster than searching the frame hierarchy, and will give us a result even in the case 3902 // where the focused frame doesn't actually contain a selection. 3903 WebFrame *focusedFrame = [self _focusedFrame]; 3904 if (focusedFrame) 3905 return focusedFrame; 3906 3907 // If the first responder is outside of our view tree, we search for a frame containing a selection. 3908 // There should be at most only one of these. 3909 return [[self mainFrame] _findFrameWithSelection]; 3910} 3911 3912- (WebBackForwardList *)backForwardList 3913{ 3914 if (!_private->page) 3915 return nil; 3916 BackForwardListImpl* list = static_cast<BackForwardListImpl*>(_private->page->backForwardList()); 3917 if (!list->enabled()) 3918 return nil; 3919 return kit(list); 3920} 3921 3922- (void)setMaintainsBackForwardList:(BOOL)flag 3923{ 3924 if (!_private->page) 3925 return; 3926 static_cast<BackForwardListImpl*>(_private->page->backForwardList())->setEnabled(flag); 3927} 3928 3929- (BOOL)goBack 3930{ 3931 if (!_private->page) 3932 return NO; 3933 3934 return _private->page->goBack(); 3935} 3936 3937- (BOOL)goForward 3938{ 3939 if (!_private->page) 3940 return NO; 3941 3942 return _private->page->goForward(); 3943} 3944 3945- (BOOL)goToBackForwardItem:(WebHistoryItem *)item 3946{ 3947 if (!_private->page) 3948 return NO; 3949 3950 _private->page->goToItem(core(item), FrameLoadTypeIndexedBackForward); 3951 return YES; 3952} 3953 3954- (void)setTextSizeMultiplier:(float)m 3955{ 3956 [self _setZoomMultiplier:m isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]]; 3957} 3958 3959- (float)textSizeMultiplier 3960{ 3961 return [self _realZoomMultiplierIsTextOnly] ? _private->zoomMultiplier : 1.0f; 3962} 3963 3964- (void)_setZoomMultiplier:(float)multiplier isTextOnly:(BOOL)isTextOnly 3965{ 3966 // NOTE: This has no visible effect when viewing a PDF (see <rdar://problem/4737380>) 3967 _private->zoomMultiplier = multiplier; 3968 _private->zoomsTextOnly = isTextOnly; 3969 3970 // FIXME: It might be nice to rework this code so that _private->zoomMultiplier doesn't exist 3971 // and instead the zoom factors stored in Frame are used. 3972 Frame* coreFrame = [self _mainCoreFrame]; 3973 if (coreFrame) { 3974 if (_private->zoomsTextOnly) 3975 coreFrame->setPageAndTextZoomFactors(1, multiplier); 3976 else 3977 coreFrame->setPageAndTextZoomFactors(multiplier, 1); 3978 } 3979} 3980 3981- (float)_zoomMultiplier:(BOOL)isTextOnly 3982{ 3983 if (isTextOnly != [self _realZoomMultiplierIsTextOnly]) 3984 return 1.0f; 3985 return _private->zoomMultiplier; 3986} 3987 3988- (float)_realZoomMultiplier 3989{ 3990 return _private->zoomMultiplier; 3991} 3992 3993- (BOOL)_realZoomMultiplierIsTextOnly 3994{ 3995 if (!_private->page) 3996 return NO; 3997 3998 return _private->zoomsTextOnly; 3999} 4000 4001#define MinimumZoomMultiplier 0.5f 4002#define MaximumZoomMultiplier 3.0f 4003#define ZoomMultiplierRatio 1.2f 4004 4005- (BOOL)_canZoomOut:(BOOL)isTextOnly 4006{ 4007 id docView = [[[self mainFrame] frameView] documentView]; 4008 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) { 4009 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView; 4010 return [zoomingDocView _canZoomOut]; 4011 } 4012 return [self _zoomMultiplier:isTextOnly] / ZoomMultiplierRatio > MinimumZoomMultiplier; 4013} 4014 4015 4016- (BOOL)_canZoomIn:(BOOL)isTextOnly 4017{ 4018 id docView = [[[self mainFrame] frameView] documentView]; 4019 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) { 4020 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView; 4021 return [zoomingDocView _canZoomIn]; 4022 } 4023 return [self _zoomMultiplier:isTextOnly] * ZoomMultiplierRatio < MaximumZoomMultiplier; 4024} 4025 4026- (IBAction)_zoomOut:(id)sender isTextOnly:(BOOL)isTextOnly 4027{ 4028 id docView = [[[self mainFrame] frameView] documentView]; 4029 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) { 4030 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView; 4031 return [zoomingDocView _zoomOut:sender]; 4032 } 4033 float newScale = [self _zoomMultiplier:isTextOnly] / ZoomMultiplierRatio; 4034 if (newScale > MinimumZoomMultiplier) 4035 [self _setZoomMultiplier:newScale isTextOnly:isTextOnly]; 4036} 4037 4038- (IBAction)_zoomIn:(id)sender isTextOnly:(BOOL)isTextOnly 4039{ 4040 id docView = [[[self mainFrame] frameView] documentView]; 4041 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) { 4042 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView; 4043 return [zoomingDocView _zoomIn:sender]; 4044 } 4045 float newScale = [self _zoomMultiplier:isTextOnly] * ZoomMultiplierRatio; 4046 if (newScale < MaximumZoomMultiplier) 4047 [self _setZoomMultiplier:newScale isTextOnly:isTextOnly]; 4048} 4049 4050- (BOOL)_canResetZoom:(BOOL)isTextOnly 4051{ 4052 id docView = [[[self mainFrame] frameView] documentView]; 4053 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) { 4054 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView; 4055 return [zoomingDocView _canResetZoom]; 4056 } 4057 return [self _zoomMultiplier:isTextOnly] != 1.0f; 4058} 4059 4060- (IBAction)_resetZoom:(id)sender isTextOnly:(BOOL)isTextOnly 4061{ 4062 id docView = [[[self mainFrame] frameView] documentView]; 4063 if ([docView conformsToProtocol:@protocol(_WebDocumentZooming)]) { 4064 id <_WebDocumentZooming> zoomingDocView = (id <_WebDocumentZooming>)docView; 4065 return [zoomingDocView _resetZoom:sender]; 4066 } 4067 if ([self _zoomMultiplier:isTextOnly] != 1.0f) 4068 [self _setZoomMultiplier:1.0f isTextOnly:isTextOnly]; 4069} 4070 4071- (void)setApplicationNameForUserAgent:(NSString *)applicationName 4072{ 4073 NSString *name = [applicationName copy]; 4074 [_private->applicationNameForUserAgent release]; 4075 _private->applicationNameForUserAgent = name; 4076 if (!_private->userAgentOverridden) 4077 _private->userAgent = String(); 4078} 4079 4080- (NSString *)applicationNameForUserAgent 4081{ 4082 return [[_private->applicationNameForUserAgent retain] autorelease]; 4083} 4084 4085- (void)setCustomUserAgent:(NSString *)userAgentString 4086{ 4087 _private->userAgent = userAgentString; 4088 _private->userAgentOverridden = userAgentString != nil; 4089} 4090 4091- (NSString *)customUserAgent 4092{ 4093 if (!_private->userAgentOverridden) 4094 return nil; 4095 return _private->userAgent; 4096} 4097 4098- (void)setMediaStyle:(NSString *)mediaStyle 4099{ 4100 if (_private->mediaStyle != mediaStyle) { 4101 [_private->mediaStyle release]; 4102 _private->mediaStyle = [mediaStyle copy]; 4103 } 4104} 4105 4106- (NSString *)mediaStyle 4107{ 4108 return _private->mediaStyle; 4109} 4110 4111- (BOOL)supportsTextEncoding 4112{ 4113 id documentView = [[[self mainFrame] frameView] documentView]; 4114 return [documentView conformsToProtocol:@protocol(WebDocumentText)] 4115 && [documentView supportsTextEncoding]; 4116} 4117 4118- (void)setCustomTextEncodingName:(NSString *)encoding 4119{ 4120 NSString *oldEncoding = [self customTextEncodingName]; 4121 if (encoding == oldEncoding || [encoding isEqualToString:oldEncoding]) 4122 return; 4123 if (Frame* mainFrame = [self _mainCoreFrame]) 4124 mainFrame->loader()->reloadWithOverrideEncoding(encoding); 4125} 4126 4127- (NSString *)_mainFrameOverrideEncoding 4128{ 4129 WebDataSource *dataSource = [[self mainFrame] provisionalDataSource]; 4130 if (dataSource == nil) 4131 dataSource = [[self mainFrame] _dataSource]; 4132 if (dataSource == nil) 4133 return nil; 4134 return nsStringNilIfEmpty([dataSource _documentLoader]->overrideEncoding()); 4135} 4136 4137- (NSString *)customTextEncodingName 4138{ 4139 return [self _mainFrameOverrideEncoding]; 4140} 4141 4142- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script 4143{ 4144 // Return statements are only valid in a function but some applications pass in scripts 4145 // prefixed with return (<rdar://problems/5103720&4616860>) since older WebKit versions 4146 // silently ignored the return. If the application is linked against an earlier version 4147 // of WebKit we will strip the return so the script wont fail. 4148 if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_JAVASCRIPT_RETURN_QUIRK)) { 4149 NSRange returnStringRange = [script rangeOfString:@"return "]; 4150 if (returnStringRange.length && !returnStringRange.location) 4151 script = [script substringFromIndex:returnStringRange.location + returnStringRange.length]; 4152 } 4153 4154 NSString *result = [[self mainFrame] _stringByEvaluatingJavaScriptFromString:script]; 4155 // The only way stringByEvaluatingJavaScriptFromString can return nil is if the frame was removed by the script 4156 // Since there's no way to get rid of the main frame, result will never ever be nil here. 4157 ASSERT(result); 4158 4159 return result; 4160} 4161 4162- (WebScriptObject *)windowScriptObject 4163{ 4164 Frame* coreFrame = [self _mainCoreFrame]; 4165 if (!coreFrame) 4166 return nil; 4167 return coreFrame->script()->windowScriptObject(); 4168} 4169 4170- (String)_userAgentString 4171{ 4172 if (_private->userAgent.isNull()) 4173 _private->userAgent = [[self class] _standardUserAgentWithApplicationName:_private->applicationNameForUserAgent]; 4174 4175 return _private->userAgent; 4176} 4177 4178// Get the appropriate user-agent string for a particular URL. 4179- (NSString *)userAgentForURL:(NSURL *)url 4180{ 4181 return [self _userAgentString]; 4182} 4183 4184- (void)setHostWindow:(NSWindow *)hostWindow 4185{ 4186 if (_private->closed && hostWindow) 4187 return; 4188 if (hostWindow == _private->hostWindow) 4189 return; 4190 4191 Frame* coreFrame = [self _mainCoreFrame]; 4192 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) 4193 [[[kit(frame) frameView] documentView] viewWillMoveToHostWindow:hostWindow]; 4194 if (_private->hostWindow && [self window] != _private->hostWindow) 4195 [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowWillCloseNotification object:_private->hostWindow]; 4196 if (hostWindow) 4197 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillClose:) name:NSWindowWillCloseNotification object:hostWindow]; 4198 [_private->hostWindow release]; 4199 _private->hostWindow = [hostWindow retain]; 4200 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) 4201 [[[kit(frame) frameView] documentView] viewDidMoveToHostWindow]; 4202 _private->page->setDeviceScaleFactor([self _deviceScaleFactor]); 4203} 4204 4205- (NSWindow *)hostWindow 4206{ 4207 // -[WebView hostWindow] can sometimes be called from the WebView's [super dealloc] method 4208 // so we check here to make sure it's not null. 4209 if (!_private) 4210 return nil; 4211 4212 return _private->hostWindow; 4213} 4214 4215- (NSView <WebDocumentView> *)documentViewAtWindowPoint:(NSPoint)point 4216{ 4217 return [[self _frameViewAtWindowPoint:point] documentView]; 4218} 4219 4220- (NSDictionary *)_elementAtWindowPoint:(NSPoint)windowPoint 4221{ 4222 WebFrameView *frameView = [self _frameViewAtWindowPoint:windowPoint]; 4223 if (!frameView) 4224 return nil; 4225 NSView <WebDocumentView> *documentView = [frameView documentView]; 4226 if ([documentView conformsToProtocol:@protocol(WebDocumentElement)]) { 4227 NSPoint point = [documentView convertPoint:windowPoint fromView:nil]; 4228 return [(NSView <WebDocumentElement> *)documentView elementAtPoint:point]; 4229 } 4230 return [NSDictionary dictionaryWithObject:[frameView webFrame] forKey:WebElementFrameKey]; 4231} 4232 4233- (NSDictionary *)elementAtPoint:(NSPoint)point 4234{ 4235 return [self _elementAtWindowPoint:[self convertPoint:point toView:nil]]; 4236} 4237 4238#if ENABLE(DRAG_SUPPORT) 4239// The following 2 internal NSView methods are called on the drag destination to make scrolling while dragging work. 4240// Scrolling while dragging will only work if the drag destination is in a scroll view. The WebView is the drag destination. 4241// When dragging to a WebView, the document subview should scroll, but it doesn't because it is not the drag destination. 4242// Forward these calls to the document subview to make its scroll view scroll. 4243- (void)_autoscrollForDraggingInfo:(id)draggingInfo timeDelta:(NSTimeInterval)repeatDelta 4244{ 4245 NSView <WebDocumentView> *documentView = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]]; 4246 [documentView _autoscrollForDraggingInfo:draggingInfo timeDelta:repeatDelta]; 4247} 4248 4249- (BOOL)_shouldAutoscrollForDraggingInfo:(id)draggingInfo 4250{ 4251 NSView <WebDocumentView> *documentView = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]]; 4252 return [documentView _shouldAutoscrollForDraggingInfo:draggingInfo]; 4253} 4254 4255- (DragApplicationFlags)applicationFlags:(id <NSDraggingInfo>)draggingInfo 4256{ 4257 uint32_t flags = 0; 4258 if ([NSApp modalWindow]) 4259 flags = DragApplicationIsModal; 4260 if ([[self window] attachedSheet]) 4261 flags |= DragApplicationHasAttachedSheet; 4262 if ([draggingInfo draggingSource] == self) 4263 flags |= DragApplicationIsSource; 4264 if ([[NSApp currentEvent] modifierFlags] & NSAlternateKeyMask) 4265 flags |= DragApplicationIsCopyKeyDown; 4266 return static_cast<DragApplicationFlags>(flags); 4267} 4268 4269- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)draggingInfo 4270{ 4271 IntPoint client([draggingInfo draggingLocation]); 4272 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window])); 4273 DragData dragData(draggingInfo, client, global, static_cast<DragOperation>([draggingInfo draggingSourceOperationMask]), [self applicationFlags:draggingInfo]); 4274 return core(self)->dragController()->dragEntered(&dragData).operation; 4275} 4276 4277- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)draggingInfo 4278{ 4279 Page* page = core(self); 4280 if (!page) 4281 return NSDragOperationNone; 4282 4283 IntPoint client([draggingInfo draggingLocation]); 4284 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window])); 4285 DragData dragData(draggingInfo, client, global, static_cast<DragOperation>([draggingInfo draggingSourceOperationMask]), [self applicationFlags:draggingInfo]); 4286 return page->dragController()->dragUpdated(&dragData).operation; 4287} 4288 4289- (void)draggingExited:(id <NSDraggingInfo>)draggingInfo 4290{ 4291 Page* page = core(self); 4292 if (!page) 4293 return; 4294 4295 IntPoint client([draggingInfo draggingLocation]); 4296 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window])); 4297 DragData dragData(draggingInfo, client, global, static_cast<DragOperation>([draggingInfo draggingSourceOperationMask]), [self applicationFlags:draggingInfo]); 4298 page->dragController()->dragExited(&dragData); 4299} 4300 4301- (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)draggingInfo 4302{ 4303 return YES; 4304} 4305 4306- (BOOL)performDragOperation:(id <NSDraggingInfo>)draggingInfo 4307{ 4308 IntPoint client([draggingInfo draggingLocation]); 4309 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window])); 4310 DragData dragData(draggingInfo, client, global, static_cast<DragOperation>([draggingInfo draggingSourceOperationMask]), [self applicationFlags:draggingInfo]); 4311 return core(self)->dragController()->performDrag(&dragData); 4312} 4313 4314- (NSView *)_hitTest:(NSPoint *)point dragTypes:(NSSet *)types 4315{ 4316 NSView *hitView = [super _hitTest:point dragTypes:types]; 4317 if (!hitView && [[self superview] mouse:*point inRect:[self frame]]) 4318 return self; 4319 return hitView; 4320} 4321#endif 4322 4323- (BOOL)acceptsFirstResponder 4324{ 4325 return [[[self mainFrame] frameView] acceptsFirstResponder]; 4326} 4327 4328- (BOOL)becomeFirstResponder 4329{ 4330 if (_private->becomingFirstResponder) { 4331 // Fix for unrepro infinite recursion reported in Radar 4448181. If we hit this assert on 4332 // a debug build, we should figure out what causes the problem and do a better fix. 4333 ASSERT_NOT_REACHED(); 4334 return NO; 4335 } 4336 4337 // This works together with setNextKeyView to splice the WebView into 4338 // the key loop similar to the way NSScrollView does this. Note that 4339 // WebFrameView has very similar code. 4340 NSWindow *window = [self window]; 4341 WebFrameView *mainFrameView = [[self mainFrame] frameView]; 4342 4343 NSResponder *previousFirstResponder = [[self window] _oldFirstResponderBeforeBecoming]; 4344 BOOL fromOutside = ![previousFirstResponder isKindOfClass:[NSView class]] || (![(NSView *)previousFirstResponder isDescendantOf:self] && previousFirstResponder != self); 4345 4346 if ([window keyViewSelectionDirection] == NSSelectingPrevious) { 4347 NSView *previousValidKeyView = [self previousValidKeyView]; 4348 if (previousValidKeyView != self && previousValidKeyView != mainFrameView) { 4349 _private->becomingFirstResponder = YES; 4350 _private->becomingFirstResponderFromOutside = fromOutside; 4351 [window makeFirstResponder:previousValidKeyView]; 4352 _private->becomingFirstResponderFromOutside = NO; 4353 _private->becomingFirstResponder = NO; 4354 return YES; 4355 } 4356 return NO; 4357 } 4358 4359 if ([mainFrameView acceptsFirstResponder]) { 4360 _private->becomingFirstResponder = YES; 4361 _private->becomingFirstResponderFromOutside = fromOutside; 4362 [window makeFirstResponder:mainFrameView]; 4363 _private->becomingFirstResponderFromOutside = NO; 4364 _private->becomingFirstResponder = NO; 4365 return YES; 4366 } 4367 4368 return NO; 4369} 4370 4371- (NSView *)_webcore_effectiveFirstResponder 4372{ 4373 if (WebFrameView *frameView = [[self mainFrame] frameView]) 4374 return [frameView _webcore_effectiveFirstResponder]; 4375 4376 return [super _webcore_effectiveFirstResponder]; 4377} 4378 4379- (void)setNextKeyView:(NSView *)view 4380{ 4381 // This works together with becomeFirstResponder to splice the WebView into 4382 // the key loop similar to the way NSScrollView does this. Note that 4383 // WebFrameView has similar code. 4384 if (WebFrameView *mainFrameView = [[self mainFrame] frameView]) { 4385 [mainFrameView setNextKeyView:view]; 4386 return; 4387 } 4388 4389 [super setNextKeyView:view]; 4390} 4391 4392static WebFrame *incrementFrame(WebFrame *frame, WebFindOptions options = 0) 4393{ 4394 Frame* coreFrame = core(frame); 4395 return kit((options & WebFindOptionsBackwards) 4396 ? coreFrame->tree()->traversePreviousWithWrap(options & WebFindOptionsWrapAround) 4397 : coreFrame->tree()->traverseNextWithWrap(options & WebFindOptionsWrapAround)); 4398} 4399 4400- (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag 4401{ 4402 return [self searchFor:string direction:forward caseSensitive:caseFlag wrap:wrapFlag startInSelection:NO]; 4403} 4404 4405+ (void)registerViewClass:(Class)viewClass representationClass:(Class)representationClass forMIMEType:(NSString *)MIMEType 4406{ 4407 [[WebFrameView _viewTypesAllowImageTypeOmission:YES] setObject:viewClass forKey:MIMEType]; 4408 [[WebDataSource _repTypesAllowImageTypeOmission:YES] setObject:representationClass forKey:MIMEType]; 4409 4410 // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed) 4411 // in the WebCore MIMEType registry. For now we're doing this in a safe, limited manner 4412 // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness 4413 if ([viewClass class] == [WebHTMLView class]) 4414 MIMETypeRegistry::getSupportedNonImageMIMETypes().add(MIMEType); 4415} 4416 4417- (void)setGroupName:(NSString *)groupName 4418{ 4419 if (!_private->page) 4420 return; 4421 _private->page->setGroupName(groupName); 4422} 4423 4424- (NSString *)groupName 4425{ 4426 if (!_private->page) 4427 return nil; 4428 return _private->page->groupName(); 4429} 4430 4431- (double)estimatedProgress 4432{ 4433 if (!_private->page) 4434 return 0.0; 4435 return _private->page->progress()->estimatedProgress(); 4436} 4437 4438- (NSArray *)pasteboardTypesForSelection 4439{ 4440 NSView <WebDocumentView> *documentView = [[[self _selectedOrMainFrame] frameView] documentView]; 4441 if ([documentView conformsToProtocol:@protocol(WebDocumentSelection)]) { 4442 return [(NSView <WebDocumentSelection> *)documentView pasteboardTypesForSelection]; 4443 } 4444 return [NSArray array]; 4445} 4446 4447- (void)writeSelectionWithPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard 4448{ 4449 WebFrame *frame = [self _selectedOrMainFrame]; 4450 if (frame && [frame _hasSelection]) { 4451 NSView <WebDocumentView> *documentView = [[frame frameView] documentView]; 4452 if ([documentView conformsToProtocol:@protocol(WebDocumentSelection)]) 4453 [(NSView <WebDocumentSelection> *)documentView writeSelectionWithPasteboardTypes:types toPasteboard:pasteboard]; 4454 } 4455} 4456 4457- (NSArray *)pasteboardTypesForElement:(NSDictionary *)element 4458{ 4459 if ([element objectForKey:WebElementImageURLKey] != nil) { 4460 return [NSPasteboard _web_writableTypesForImageIncludingArchive:([element objectForKey:WebElementDOMNodeKey] != nil)]; 4461 } else if ([element objectForKey:WebElementLinkURLKey] != nil) { 4462 return [NSPasteboard _web_writableTypesForURL]; 4463 } else if ([[element objectForKey:WebElementIsSelectedKey] boolValue]) { 4464 return [self pasteboardTypesForSelection]; 4465 } 4466 return [NSArray array]; 4467} 4468 4469- (void)writeElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard 4470{ 4471 if ([element objectForKey:WebElementImageURLKey] != nil) { 4472 [self _writeImageForElement:element withPasteboardTypes:types toPasteboard:pasteboard]; 4473 } else if ([element objectForKey:WebElementLinkURLKey] != nil) { 4474 [self _writeLinkElement:element withPasteboardTypes:types toPasteboard:pasteboard]; 4475 } else if ([[element objectForKey:WebElementIsSelectedKey] boolValue]) { 4476 [self writeSelectionWithPasteboardTypes:types toPasteboard:pasteboard]; 4477 } 4478} 4479 4480- (void)moveDragCaretToPoint:(NSPoint)point 4481{ 4482#if ENABLE(DRAG_SUPPORT) 4483 if (Page* page = core(self)) 4484 page->dragController()->placeDragCaret(IntPoint([self convertPoint:point toView:nil])); 4485#endif 4486} 4487 4488- (void)removeDragCaret 4489{ 4490#if ENABLE(DRAG_SUPPORT) 4491 if (Page* page = core(self)) 4492 page->dragController()->dragEnded(); 4493#endif 4494} 4495 4496- (void)setMainFrameURL:(NSString *)URLString 4497{ 4498 NSURL *url; 4499 if ([URLString hasPrefix:@"/"]) 4500 url = [NSURL fileURLWithPath:URLString]; 4501 else 4502 url = [NSURL _web_URLWithDataAsString:URLString]; 4503 4504 [[self mainFrame] loadRequest:[NSURLRequest requestWithURL:url]]; 4505} 4506 4507- (NSString *)mainFrameURL 4508{ 4509 WebDataSource *ds; 4510 ds = [[self mainFrame] provisionalDataSource]; 4511 if (!ds) 4512 ds = [[self mainFrame] _dataSource]; 4513 return [[[ds request] URL] _web_originalDataAsString]; 4514} 4515 4516- (BOOL)isLoading 4517{ 4518 LOG (Bindings, "isLoading = %d", (int)[self _isLoading]); 4519 return [self _isLoading]; 4520} 4521 4522- (NSString *)mainFrameTitle 4523{ 4524 NSString *mainFrameTitle = [[[self mainFrame] _dataSource] pageTitle]; 4525 return (mainFrameTitle != nil) ? mainFrameTitle : (NSString *)@""; 4526} 4527 4528- (NSImage *)mainFrameIcon 4529{ 4530 return [[WebIconDatabase sharedIconDatabase] iconForURL:[[[[self mainFrame] _dataSource] _URL] _web_originalDataAsString] withSize:WebIconSmallSize]; 4531} 4532 4533- (DOMDocument *)mainFrameDocument 4534{ 4535 // only return the actual value if the state we're in gives NSTreeController 4536 // enough time to release its observers on the old model 4537 if (_private->mainFrameDocumentReady) 4538 return [[self mainFrame] DOMDocument]; 4539 return nil; 4540} 4541 4542- (void)setDrawsBackground:(BOOL)drawsBackground 4543{ 4544 if (_private->drawsBackground == drawsBackground) 4545 return; 4546 _private->drawsBackground = drawsBackground; 4547 [[self mainFrame] _updateBackgroundAndUpdatesWhileOffscreen]; 4548} 4549 4550- (BOOL)drawsBackground 4551{ 4552 // This method can be called beneath -[NSView dealloc] after we have cleared _private, 4553 // indirectly via -[WebFrameView viewDidMoveToWindow]. 4554 return !_private || _private->drawsBackground; 4555} 4556 4557- (void)setShouldUpdateWhileOffscreen:(BOOL)updateWhileOffscreen 4558{ 4559 if (_private->shouldUpdateWhileOffscreen == updateWhileOffscreen) 4560 return; 4561 _private->shouldUpdateWhileOffscreen = updateWhileOffscreen; 4562 [[self mainFrame] _updateBackgroundAndUpdatesWhileOffscreen]; 4563} 4564 4565- (BOOL)shouldUpdateWhileOffscreen 4566{ 4567 return _private->shouldUpdateWhileOffscreen; 4568} 4569 4570- (void)setCurrentNodeHighlight:(WebNodeHighlight *)nodeHighlight 4571{ 4572 id old = _private->currentNodeHighlight; 4573 _private->currentNodeHighlight = [nodeHighlight retain]; 4574 [old release]; 4575} 4576 4577- (WebNodeHighlight *)currentNodeHighlight 4578{ 4579 return _private->currentNodeHighlight; 4580} 4581 4582- (NSView *)previousValidKeyView 4583{ 4584 NSView *result = [super previousValidKeyView]; 4585 4586 // Work around AppKit bug 6905484. If the result is a view that's inside this one, it's 4587 // possible it is the wrong answer, because the fact that it's a descendant causes the 4588 // code that implements key view redirection to fail; this means we won't redirect to 4589 // the toolbar, for example, when we hit the edge of a window. Since the bug is specific 4590 // to cases where the receiver of previousValidKeyView is an ancestor of the last valid 4591 // key view in the loop, we can sidestep it by walking along previous key views until 4592 // we find one that is not a superview, then using that to call previousValidKeyView. 4593 4594 if (![result isDescendantOf:self]) 4595 return result; 4596 4597 // Use a visited set so we don't loop indefinitely when walking crazy key loops. 4598 // AppKit uses such sets internally and we want our loop to be as robust as its loops. 4599 RetainPtr<CFMutableSetRef> visitedViews = adoptCF(CFSetCreateMutable(0, 0, 0)); 4600 CFSetAddValue(visitedViews.get(), result); 4601 4602 NSView *previousView = self; 4603 do { 4604 CFSetAddValue(visitedViews.get(), previousView); 4605 previousView = [previousView previousKeyView]; 4606 if (!previousView || CFSetGetValue(visitedViews.get(), previousView)) 4607 return result; 4608 } while ([result isDescendantOf:previousView]); 4609 return [previousView previousValidKeyView]; 4610} 4611 4612@end 4613 4614@implementation WebView (WebIBActions) 4615 4616- (IBAction)takeStringURLFrom: sender 4617{ 4618 NSString *URLString = [sender stringValue]; 4619 4620 [[self mainFrame] loadRequest: [NSURLRequest requestWithURL: [NSURL _web_URLWithDataAsString: URLString]]]; 4621} 4622 4623- (BOOL)canGoBack 4624{ 4625 if (!_private->page || _private->page->defersLoading()) 4626 return NO; 4627 4628 return !!_private->page->backForwardList()->backItem(); 4629} 4630 4631- (BOOL)canGoForward 4632{ 4633 if (!_private->page || _private->page->defersLoading()) 4634 return NO; 4635 4636 return !!_private->page->backForwardList()->forwardItem(); 4637} 4638 4639- (IBAction)goBack:(id)sender 4640{ 4641 [self goBack]; 4642} 4643 4644- (IBAction)goForward:(id)sender 4645{ 4646 [self goForward]; 4647} 4648 4649- (IBAction)stopLoading:(id)sender 4650{ 4651 [[self mainFrame] stopLoading]; 4652} 4653 4654- (IBAction)reload:(id)sender 4655{ 4656 [[self mainFrame] reload]; 4657} 4658 4659- (IBAction)reloadFromOrigin:(id)sender 4660{ 4661 [[self mainFrame] reloadFromOrigin]; 4662} 4663 4664// FIXME: This code should move into WebCore so that it is not duplicated in each WebKit. 4665// (This includes canMakeTextSmaller/Larger, makeTextSmaller/Larger, and canMakeTextStandardSize/makeTextStandardSize) 4666- (BOOL)canMakeTextSmaller 4667{ 4668 return [self _canZoomOut:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]]; 4669} 4670 4671- (IBAction)makeTextSmaller:(id)sender 4672{ 4673 return [self _zoomOut:sender isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]]; 4674} 4675 4676- (BOOL)canMakeTextLarger 4677{ 4678 return [self _canZoomIn:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]]; 4679} 4680 4681- (IBAction)makeTextLarger:(id)sender 4682{ 4683 return [self _zoomIn:sender isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]]; 4684} 4685 4686- (BOOL)canMakeTextStandardSize 4687{ 4688 return [self _canResetZoom:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]]; 4689} 4690 4691- (IBAction)makeTextStandardSize:(id)sender 4692{ 4693 return [self _resetZoom:sender isTextOnly:![[NSUserDefaults standardUserDefaults] boolForKey:WebKitDebugFullPageZoomPreferenceKey]]; 4694} 4695 4696- (IBAction)toggleSmartInsertDelete:(id)sender 4697{ 4698 [self setSmartInsertDeleteEnabled:![self smartInsertDeleteEnabled]]; 4699} 4700 4701- (IBAction)toggleContinuousSpellChecking:(id)sender 4702{ 4703 [self setContinuousSpellCheckingEnabled:![self isContinuousSpellCheckingEnabled]]; 4704} 4705 4706- (BOOL)_responderValidateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item 4707{ 4708 id responder = [self _responderForResponderOperations]; 4709 if (responder != self && [responder respondsToSelector:[item action]]) { 4710 if ([responder respondsToSelector:@selector(validateUserInterfaceItemWithoutDelegate:)]) 4711 return [responder validateUserInterfaceItemWithoutDelegate:item]; 4712 if ([responder respondsToSelector:@selector(validateUserInterfaceItem:)]) 4713 return [responder validateUserInterfaceItem:item]; 4714 return YES; 4715 } 4716 return NO; 4717} 4718 4719#define VALIDATE(name) \ 4720 else if (action == @selector(name:)) { return [self _responderValidateUserInterfaceItem:item]; } 4721 4722- (BOOL)validateUserInterfaceItemWithoutDelegate:(id <NSValidatedUserInterfaceItem>)item 4723{ 4724 SEL action = [item action]; 4725 4726 if (action == @selector(goBack:)) { 4727 return [self canGoBack]; 4728 } else if (action == @selector(goForward:)) { 4729 return [self canGoForward]; 4730 } else if (action == @selector(makeTextLarger:)) { 4731 return [self canMakeTextLarger]; 4732 } else if (action == @selector(makeTextSmaller:)) { 4733 return [self canMakeTextSmaller]; 4734 } else if (action == @selector(makeTextStandardSize:)) { 4735 return [self canMakeTextStandardSize]; 4736 } else if (action == @selector(reload:)) { 4737 return [[self mainFrame] _dataSource] != nil; 4738 } else if (action == @selector(stopLoading:)) { 4739 return [self _isLoading]; 4740 } else if (action == @selector(toggleContinuousSpellChecking:)) { 4741 BOOL checkMark = NO; 4742 BOOL retVal = NO; 4743 if ([self _continuousCheckingAllowed]) { 4744 checkMark = [self isContinuousSpellCheckingEnabled]; 4745 retVal = YES; 4746 } 4747 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) { 4748 NSMenuItem *menuItem = (NSMenuItem *)item; 4749 [menuItem setState:checkMark ? NSOnState : NSOffState]; 4750 } 4751 return retVal; 4752 } else if (action == @selector(toggleSmartInsertDelete:)) { 4753 BOOL checkMark = [self smartInsertDeleteEnabled]; 4754 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) { 4755 NSMenuItem *menuItem = (NSMenuItem *)item; 4756 [menuItem setState:checkMark ? NSOnState : NSOffState]; 4757 } 4758 return YES; 4759 } else if (action == @selector(toggleGrammarChecking:)) { 4760 BOOL checkMark = [self isGrammarCheckingEnabled]; 4761 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) { 4762 NSMenuItem *menuItem = (NSMenuItem *)item; 4763 [menuItem setState:checkMark ? NSOnState : NSOffState]; 4764 } 4765 return YES; 4766 } else if (action == @selector(toggleAutomaticQuoteSubstitution:)) { 4767 BOOL checkMark = [self isAutomaticQuoteSubstitutionEnabled]; 4768 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) { 4769 NSMenuItem *menuItem = (NSMenuItem *)item; 4770 [menuItem setState:checkMark ? NSOnState : NSOffState]; 4771 } 4772 return YES; 4773 } else if (action == @selector(toggleAutomaticLinkDetection:)) { 4774 BOOL checkMark = [self isAutomaticLinkDetectionEnabled]; 4775 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) { 4776 NSMenuItem *menuItem = (NSMenuItem *)item; 4777 [menuItem setState:checkMark ? NSOnState : NSOffState]; 4778 } 4779 return YES; 4780 } else if (action == @selector(toggleAutomaticDashSubstitution:)) { 4781 BOOL checkMark = [self isAutomaticDashSubstitutionEnabled]; 4782 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) { 4783 NSMenuItem *menuItem = (NSMenuItem *)item; 4784 [menuItem setState:checkMark ? NSOnState : NSOffState]; 4785 } 4786 return YES; 4787 } else if (action == @selector(toggleAutomaticTextReplacement:)) { 4788 BOOL checkMark = [self isAutomaticTextReplacementEnabled]; 4789 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) { 4790 NSMenuItem *menuItem = (NSMenuItem *)item; 4791 [menuItem setState:checkMark ? NSOnState : NSOffState]; 4792 } 4793 return YES; 4794 } else if (action == @selector(toggleAutomaticSpellingCorrection:)) { 4795 BOOL checkMark = [self isAutomaticSpellingCorrectionEnabled]; 4796 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) { 4797 NSMenuItem *menuItem = (NSMenuItem *)item; 4798 [menuItem setState:checkMark ? NSOnState : NSOffState]; 4799 } 4800 return YES; 4801 } 4802 FOR_EACH_RESPONDER_SELECTOR(VALIDATE) 4803 4804 return YES; 4805} 4806 4807- (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item 4808{ 4809 BOOL result = [self validateUserInterfaceItemWithoutDelegate:item]; 4810 return CallUIDelegateReturningBoolean(result, self, @selector(webView:validateUserInterfaceItem:defaultValidation:), item, result); 4811} 4812 4813@end 4814 4815@implementation WebView (WebPendingPublic) 4816 4817- (void)scheduleInRunLoop:(NSRunLoop *)runLoop forMode:(NSString *)mode 4818{ 4819#if USE(CFNETWORK) 4820 CFRunLoopRef schedulePairRunLoop = [runLoop getCFRunLoop]; 4821#else 4822 NSRunLoop *schedulePairRunLoop = runLoop; 4823#endif 4824 if (runLoop && mode) 4825 core(self)->addSchedulePair(SchedulePair::create(schedulePairRunLoop, (CFStringRef)mode)); 4826} 4827 4828- (void)unscheduleFromRunLoop:(NSRunLoop *)runLoop forMode:(NSString *)mode 4829{ 4830#if USE(CFNETWORK) 4831 CFRunLoopRef schedulePairRunLoop = [runLoop getCFRunLoop]; 4832#else 4833 NSRunLoop *schedulePairRunLoop = runLoop; 4834#endif 4835 if (runLoop && mode) 4836 core(self)->removeSchedulePair(SchedulePair::create(schedulePairRunLoop, (CFStringRef)mode)); 4837} 4838 4839static BOOL findString(NSView <WebDocumentSearching> *searchView, NSString *string, WebFindOptions options) 4840{ 4841 if ([searchView conformsToProtocol:@protocol(WebDocumentOptionsSearching)]) 4842 return [(NSView <WebDocumentOptionsSearching> *)searchView _findString:string options:options]; 4843 if ([searchView conformsToProtocol:@protocol(WebDocumentIncrementalSearching)]) 4844 return [(NSView <WebDocumentIncrementalSearching> *)searchView searchFor:string direction:!(options & WebFindOptionsBackwards) caseSensitive:!(options & WebFindOptionsCaseInsensitive) wrap:!!(options & WebFindOptionsWrapAround) startInSelection:!!(options & WebFindOptionsStartInSelection)]; 4845 return [searchView searchFor:string direction:!(options & WebFindOptionsBackwards) caseSensitive:!(options & WebFindOptionsCaseInsensitive) wrap:!!(options & WebFindOptionsWrapAround)]; 4846} 4847 4848- (BOOL)findString:(NSString *)string options:(WebFindOptions)options 4849{ 4850 if (_private->closed) 4851 return NO; 4852 4853 // Get the frame holding the selection, or start with the main frame 4854 WebFrame *startFrame = [self _selectedOrMainFrame]; 4855 4856 // Search the first frame, then all the other frames, in order 4857 NSView <WebDocumentSearching> *startSearchView = nil; 4858 WebFrame *frame = startFrame; 4859 do { 4860 WebFrame *nextFrame = incrementFrame(frame, options); 4861 4862 BOOL onlyOneFrame = (frame == nextFrame); 4863 ASSERT(!onlyOneFrame || frame == startFrame); 4864 4865 id <WebDocumentView> view = [[frame frameView] documentView]; 4866 if ([view conformsToProtocol:@protocol(WebDocumentSearching)]) { 4867 NSView <WebDocumentSearching> *searchView = (NSView <WebDocumentSearching> *)view; 4868 4869 if (frame == startFrame) 4870 startSearchView = searchView; 4871 4872 // In some cases we have to search some content twice; see comment later in this method. 4873 // We can avoid ever doing this in the common one-frame case by passing the wrap option through 4874 // here, and then bailing out before we get to the code that would search again in the 4875 // same content. 4876 WebFindOptions optionsForThisPass = onlyOneFrame ? options : (options & ~WebFindOptionsWrapAround); 4877 4878 if (findString(searchView, string, optionsForThisPass)) { 4879 if (frame != startFrame) 4880 [startFrame _clearSelection]; 4881 [[self window] makeFirstResponder:searchView]; 4882 return YES; 4883 } 4884 4885 if (onlyOneFrame) 4886 return NO; 4887 } 4888 frame = nextFrame; 4889 } while (frame && frame != startFrame); 4890 4891 // 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 4892 // 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 4893 // way to make sure the entire frame is searched is to pass WebFindOptionsWrapAround. When there are no matches, this will search 4894 // some content that we already searched on the first pass. In the worst case, we could search the entire contents of this frame twice. 4895 // To fix this, we'd need to add a mechanism to specify a range in which to search. 4896 if ((options & WebFindOptionsWrapAround) && startSearchView) { 4897 if (findString(startSearchView, string, options)) { 4898 [[self window] makeFirstResponder:startSearchView]; 4899 return YES; 4900 } 4901 } 4902 return NO; 4903} 4904 4905- (DOMRange *)DOMRangeOfString:(NSString *)string relativeTo:(DOMRange *)previousRange options:(WebFindOptions)options 4906{ 4907 if (!_private->page) 4908 return nil; 4909 4910 return kit(_private->page->rangeOfString(string, core(previousRange), coreOptions(options)).get()); 4911} 4912 4913#if __MAC_OS_X_VERSION_MIN_REQUIRED <= 1070 4914// FIXME: Remove once WebKit no longer needs to support versions of Safari that call this. 4915- (void)setHoverFeedbackSuspended:(BOOL)newValue 4916{ 4917} 4918 4919// FIXME: Remove once WebKit no longer needs to support versions of Safari that call this. 4920- (BOOL)isHoverFeedbackSuspended 4921{ 4922 return NO; 4923} 4924#endif 4925 4926- (void)setMainFrameDocumentReady:(BOOL)mainFrameDocumentReady 4927{ 4928 // by setting this to NO, calls to mainFrameDocument are forced to return nil 4929 // setting this to YES lets it return the actual DOMDocument value 4930 // we use this to tell NSTreeController to reset its observers and clear its state 4931 if (_private->mainFrameDocumentReady == mainFrameDocumentReady) 4932 return; 4933 [self _willChangeValueForKey:_WebMainFrameDocumentKey]; 4934 _private->mainFrameDocumentReady = mainFrameDocumentReady; 4935 [self _didChangeValueForKey:_WebMainFrameDocumentKey]; 4936 // this will cause observers to call mainFrameDocument where this flag will be checked 4937} 4938 4939- (void)setTabKeyCyclesThroughElements:(BOOL)cyclesElements 4940{ 4941 _private->tabKeyCyclesThroughElementsChanged = YES; 4942 if (_private->page) 4943 _private->page->setTabKeyCyclesThroughElements(cyclesElements); 4944} 4945 4946- (BOOL)tabKeyCyclesThroughElements 4947{ 4948 return _private->page && _private->page->tabKeyCyclesThroughElements(); 4949} 4950 4951- (void)setScriptDebugDelegate:(id)delegate 4952{ 4953 _private->scriptDebugDelegate = delegate; 4954 [self _cacheScriptDebugDelegateImplementations]; 4955 4956 if (delegate) 4957 [self _attachScriptDebuggerToAllFrames]; 4958 else 4959 [self _detachScriptDebuggerFromAllFrames]; 4960} 4961 4962- (id)scriptDebugDelegate 4963{ 4964 return _private->scriptDebugDelegate; 4965} 4966 4967- (void)setHistoryDelegate:(id)delegate 4968{ 4969 _private->historyDelegate = delegate; 4970 [self _cacheHistoryDelegateImplementations]; 4971} 4972 4973- (id)historyDelegate 4974{ 4975 return _private->historyDelegate; 4976} 4977 4978- (BOOL)shouldClose 4979{ 4980 Frame* coreFrame = [self _mainCoreFrame]; 4981 if (!coreFrame) 4982 return YES; 4983 return coreFrame->loader()->shouldClose(); 4984} 4985 4986static NSAppleEventDescriptor* aeDescFromJSValue(ExecState* exec, JSC::JSValue jsValue) 4987{ 4988 NSAppleEventDescriptor* aeDesc = 0; 4989 if (jsValue.isBoolean()) 4990 return [NSAppleEventDescriptor descriptorWithBoolean:jsValue.asBoolean()]; 4991 if (jsValue.isString()) 4992 return [NSAppleEventDescriptor descriptorWithString:jsValue.getString(exec)]; 4993 if (jsValue.isNumber()) { 4994 double value = jsValue.asNumber(); 4995 int intValue = value; 4996 if (value == intValue) 4997 return [NSAppleEventDescriptor descriptorWithDescriptorType:typeSInt32 bytes:&intValue length:sizeof(intValue)]; 4998 return [NSAppleEventDescriptor descriptorWithDescriptorType:typeIEEE64BitFloatingPoint bytes:&value length:sizeof(value)]; 4999 } 5000 if (jsValue.isObject()) { 5001 JSObject* object = jsValue.getObject(); 5002 if (object->inherits(&DateInstance::s_info)) { 5003 DateInstance* date = static_cast<DateInstance*>(object); 5004 double ms = date->internalNumber(); 5005 if (!std::isnan(ms)) { 5006 CFAbsoluteTime utcSeconds = ms / 1000 - kCFAbsoluteTimeIntervalSince1970; 5007 LongDateTime ldt; 5008 if (noErr == UCConvertCFAbsoluteTimeToLongDateTime(utcSeconds, &ldt)) 5009 return [NSAppleEventDescriptor descriptorWithDescriptorType:typeLongDateTime bytes:&ldt length:sizeof(ldt)]; 5010 } 5011 } 5012 else if (object->inherits(&JSArray::s_info)) { 5013 DEFINE_STATIC_LOCAL(HashSet<JSObject*>, visitedElems, ()); 5014 if (!visitedElems.contains(object)) { 5015 visitedElems.add(object); 5016 5017 JSArray* array = static_cast<JSArray*>(object); 5018 aeDesc = [NSAppleEventDescriptor listDescriptor]; 5019 unsigned numItems = array->length(); 5020 for (unsigned i = 0; i < numItems; ++i) 5021 [aeDesc insertDescriptor:aeDescFromJSValue(exec, array->get(exec, i)) atIndex:0]; 5022 5023 visitedElems.remove(object); 5024 return aeDesc; 5025 } 5026 } 5027 JSC::JSValue primitive = object->toPrimitive(exec); 5028 if (exec->hadException()) { 5029 exec->clearException(); 5030 return [NSAppleEventDescriptor nullDescriptor]; 5031 } 5032 return aeDescFromJSValue(exec, primitive); 5033 } 5034 if (jsValue.isUndefined()) 5035 return [NSAppleEventDescriptor descriptorWithTypeCode:cMissingValue]; 5036 ASSERT(jsValue.isNull()); 5037 return [NSAppleEventDescriptor nullDescriptor]; 5038} 5039 5040- (NSAppleEventDescriptor *)aeDescByEvaluatingJavaScriptFromString:(NSString *)script 5041{ 5042 Frame* coreFrame = [self _mainCoreFrame]; 5043 if (!coreFrame) 5044 return nil; 5045 if (!coreFrame->document()) 5046 return nil; 5047 JSC::JSValue result = coreFrame->script()->executeScript(script, true).jsValue(); 5048 if (!result) // FIXME: pass errors 5049 return 0; 5050 JSLockHolder lock(coreFrame->script()->globalObject(mainThreadNormalWorld())->globalExec()); 5051 return aeDescFromJSValue(coreFrame->script()->globalObject(mainThreadNormalWorld())->globalExec(), result); 5052} 5053 5054- (BOOL)canMarkAllTextMatches 5055{ 5056 if (_private->closed) 5057 return NO; 5058 5059 WebFrame *frame = [self mainFrame]; 5060 do { 5061 id <WebDocumentView> view = [[frame frameView] documentView]; 5062 if (view && ![view conformsToProtocol:@protocol(WebMultipleTextMatches)]) 5063 return NO; 5064 5065 frame = incrementFrame(frame); 5066 } while (frame); 5067 5068 return YES; 5069} 5070 5071- (NSUInteger)countMatchesForText:(NSString *)string options:(WebFindOptions)options highlight:(BOOL)highlight limit:(NSUInteger)limit markMatches:(BOOL)markMatches 5072{ 5073 return [self countMatchesForText:string inDOMRange:nil options:options highlight:highlight limit:limit markMatches:markMatches]; 5074} 5075 5076- (NSUInteger)countMatchesForText:(NSString *)string inDOMRange:(DOMRange *)range options:(WebFindOptions)options highlight:(BOOL)highlight limit:(NSUInteger)limit markMatches:(BOOL)markMatches 5077{ 5078 if (_private->closed) 5079 return 0; 5080 5081 WebFrame *frame = [self mainFrame]; 5082 unsigned matchCount = 0; 5083 do { 5084 id <WebDocumentView> view = [[frame frameView] documentView]; 5085 if ([view conformsToProtocol:@protocol(WebMultipleTextMatches)]) { 5086 if (markMatches) 5087 [(NSView <WebMultipleTextMatches>*)view setMarkedTextMatchesAreHighlighted:highlight]; 5088 5089 ASSERT(limit == 0 || matchCount < limit); 5090 matchCount += [(NSView <WebMultipleTextMatches>*)view countMatchesForText:string inDOMRange:range options:options limit:(limit == 0 ? 0 : limit - matchCount) markMatches:markMatches]; 5091 5092 // Stop looking if we've reached the limit. A limit of 0 means no limit. 5093 if (limit > 0 && matchCount >= limit) 5094 break; 5095 } 5096 5097 frame = incrementFrame(frame); 5098 } while (frame); 5099 5100 return matchCount; 5101} 5102 5103- (void)unmarkAllTextMatches 5104{ 5105 if (_private->closed) 5106 return; 5107 5108 WebFrame *frame = [self mainFrame]; 5109 do { 5110 id <WebDocumentView> view = [[frame frameView] documentView]; 5111 if ([view conformsToProtocol:@protocol(WebMultipleTextMatches)]) 5112 [(NSView <WebMultipleTextMatches>*)view unmarkAllTextMatches]; 5113 5114 frame = incrementFrame(frame); 5115 } while (frame); 5116} 5117 5118- (NSArray *)rectsForTextMatches 5119{ 5120 if (_private->closed) 5121 return [NSArray array]; 5122 5123 NSMutableArray *result = [NSMutableArray array]; 5124 WebFrame *frame = [self mainFrame]; 5125 do { 5126 id <WebDocumentView> view = [[frame frameView] documentView]; 5127 if ([view conformsToProtocol:@protocol(WebMultipleTextMatches)]) { 5128 NSView <WebMultipleTextMatches> *documentView = (NSView <WebMultipleTextMatches> *)view; 5129 NSRect documentViewVisibleRect = [documentView visibleRect]; 5130 NSArray *originalRects = [documentView rectsForTextMatches]; 5131 unsigned rectCount = [originalRects count]; 5132 unsigned rectIndex; 5133 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 5134 for (rectIndex = 0; rectIndex < rectCount; ++rectIndex) { 5135 NSRect r = [[originalRects objectAtIndex:rectIndex] rectValue]; 5136 // Clip rect to document view's visible rect so rect is confined to subframe 5137 r = NSIntersectionRect(r, documentViewVisibleRect); 5138 if (NSIsEmptyRect(r)) 5139 continue; 5140 5141 // Convert rect to our coordinate system 5142 r = [documentView convertRect:r toView:self]; 5143 [result addObject:[NSValue valueWithRect:r]]; 5144 if (rectIndex % 10 == 0) { 5145 [pool drain]; 5146 pool = [[NSAutoreleasePool alloc] init]; 5147 } 5148 } 5149 [pool drain]; 5150 } 5151 5152 frame = incrementFrame(frame); 5153 } while (frame); 5154 5155 return result; 5156} 5157 5158- (void)scrollDOMRangeToVisible:(DOMRange *)range 5159{ 5160 [[[[range startContainer] ownerDocument] webFrame] _scrollDOMRangeToVisible:range]; 5161} 5162 5163- (BOOL)allowsUndo 5164{ 5165 return _private->allowsUndo; 5166} 5167 5168- (void)setAllowsUndo:(BOOL)flag 5169{ 5170 _private->allowsUndo = flag; 5171} 5172 5173- (void)setPageSizeMultiplier:(float)m 5174{ 5175 [self _setZoomMultiplier:m isTextOnly:NO]; 5176} 5177 5178- (float)pageSizeMultiplier 5179{ 5180 return ![self _realZoomMultiplierIsTextOnly] ? _private->zoomMultiplier : 1.0f; 5181} 5182 5183- (BOOL)canZoomPageIn 5184{ 5185 return [self _canZoomIn:NO]; 5186} 5187 5188- (IBAction)zoomPageIn:(id)sender 5189{ 5190 return [self _zoomIn:sender isTextOnly:NO]; 5191} 5192 5193- (BOOL)canZoomPageOut 5194{ 5195 return [self _canZoomOut:NO]; 5196} 5197 5198- (IBAction)zoomPageOut:(id)sender 5199{ 5200 return [self _zoomOut:sender isTextOnly:NO]; 5201} 5202 5203- (BOOL)canResetPageZoom 5204{ 5205 return [self _canResetZoom:NO]; 5206} 5207 5208- (IBAction)resetPageZoom:(id)sender 5209{ 5210 return [self _resetZoom:sender isTextOnly:NO]; 5211} 5212 5213- (void)setMediaVolume:(float)volume 5214{ 5215 if (_private->page) 5216 _private->page->setMediaVolume(volume); 5217} 5218 5219- (float)mediaVolume 5220{ 5221 if (!_private->page) 5222 return 0; 5223 5224 return _private->page->mediaVolume(); 5225} 5226 5227- (void)addVisitedLinks:(NSArray *)visitedLinks 5228{ 5229 PageGroup& group = core(self)->group(); 5230 5231 NSEnumerator *enumerator = [visitedLinks objectEnumerator]; 5232 while (NSString *url = [enumerator nextObject]) { 5233 size_t length = [url length]; 5234 const UChar* characters = CFStringGetCharactersPtr(reinterpret_cast<CFStringRef>(url)); 5235 if (characters) 5236 group.addVisitedLink(characters, length); 5237 else { 5238 Vector<UChar, 512> buffer(length); 5239 [url getCharacters:buffer.data()]; 5240 group.addVisitedLink(buffer.data(), length); 5241 } 5242 } 5243} 5244 5245@end 5246 5247@implementation WebView (WebViewPrintingPrivate) 5248 5249- (float)_headerHeight 5250{ 5251 return CallUIDelegateReturningFloat(self, @selector(webViewHeaderHeight:)); 5252} 5253 5254- (float)_footerHeight 5255{ 5256 return CallUIDelegateReturningFloat(self, @selector(webViewFooterHeight:)); 5257} 5258 5259- (void)_drawHeaderInRect:(NSRect)rect 5260{ 5261#ifdef DEBUG_HEADER_AND_FOOTER 5262 NSGraphicsContext *currentContext = [NSGraphicsContext currentContext]; 5263 [currentContext saveGraphicsState]; 5264 [[NSColor yellowColor] set]; 5265 NSRectFill(rect); 5266 [currentContext restoreGraphicsState]; 5267#endif 5268 5269 SEL selector = @selector(webView:drawHeaderInRect:); 5270 if (![_private->UIDelegate respondsToSelector:selector]) 5271 return; 5272 5273 NSGraphicsContext *currentContext = [NSGraphicsContext currentContext]; 5274 [currentContext saveGraphicsState]; 5275 5276 NSRectClip(rect); 5277 CallUIDelegate(self, selector, rect); 5278 5279 [currentContext restoreGraphicsState]; 5280} 5281 5282- (void)_drawFooterInRect:(NSRect)rect 5283{ 5284#ifdef DEBUG_HEADER_AND_FOOTER 5285 NSGraphicsContext *currentContext = [NSGraphicsContext currentContext]; 5286 [currentContext saveGraphicsState]; 5287 [[NSColor cyanColor] set]; 5288 NSRectFill(rect); 5289 [currentContext restoreGraphicsState]; 5290#endif 5291 5292 SEL selector = @selector(webView:drawFooterInRect:); 5293 if (![_private->UIDelegate respondsToSelector:selector]) 5294 return; 5295 5296 NSGraphicsContext *currentContext = [NSGraphicsContext currentContext]; 5297 [currentContext saveGraphicsState]; 5298 5299 NSRectClip(rect); 5300 CallUIDelegate(self, selector, rect); 5301 5302 [currentContext restoreGraphicsState]; 5303} 5304 5305- (void)_adjustPrintingMarginsForHeaderAndFooter 5306{ 5307 NSPrintOperation *op = [NSPrintOperation currentOperation]; 5308 NSPrintInfo *info = [op printInfo]; 5309 NSMutableDictionary *infoDictionary = [info dictionary]; 5310 5311 // We need to modify the top and bottom margins in the NSPrintInfo to account for the space needed by the 5312 // header and footer. Because this method can be called more than once on the same NSPrintInfo (see 5038087), 5313 // we stash away the unmodified top and bottom margins the first time this method is called, and we read from 5314 // those stashed-away values on subsequent calls. 5315 float originalTopMargin; 5316 float originalBottomMargin; 5317 NSNumber *originalTopMarginNumber = [infoDictionary objectForKey:WebKitOriginalTopPrintingMarginKey]; 5318 if (!originalTopMarginNumber) { 5319 ASSERT(![infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey]); 5320 originalTopMargin = [info topMargin]; 5321 originalBottomMargin = [info bottomMargin]; 5322 [infoDictionary setObject:[NSNumber numberWithFloat:originalTopMargin] forKey:WebKitOriginalTopPrintingMarginKey]; 5323 [infoDictionary setObject:[NSNumber numberWithFloat:originalBottomMargin] forKey:WebKitOriginalBottomPrintingMarginKey]; 5324 } else { 5325 ASSERT([originalTopMarginNumber isKindOfClass:[NSNumber class]]); 5326 ASSERT([[infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey] isKindOfClass:[NSNumber class]]); 5327 originalTopMargin = [originalTopMarginNumber floatValue]; 5328 originalBottomMargin = [[infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey] floatValue]; 5329 } 5330 5331 float scale = [op _web_pageSetupScaleFactor]; 5332 [info setTopMargin:originalTopMargin + [self _headerHeight] * scale]; 5333 [info setBottomMargin:originalBottomMargin + [self _footerHeight] * scale]; 5334} 5335 5336- (void)_drawHeaderAndFooter 5337{ 5338 // The header and footer rect height scales with the page, but the width is always 5339 // all the way across the printed page (inset by printing margins). 5340 NSPrintOperation *op = [NSPrintOperation currentOperation]; 5341 float scale = [op _web_pageSetupScaleFactor]; 5342 NSPrintInfo *printInfo = [op printInfo]; 5343 NSSize paperSize = [printInfo paperSize]; 5344 float headerFooterLeft = [printInfo leftMargin]/scale; 5345 float headerFooterWidth = (paperSize.width - ([printInfo leftMargin] + [printInfo rightMargin]))/scale; 5346 NSRect footerRect = NSMakeRect(headerFooterLeft, [printInfo bottomMargin]/scale - [self _footerHeight] , 5347 headerFooterWidth, [self _footerHeight]); 5348 NSRect headerRect = NSMakeRect(headerFooterLeft, (paperSize.height - [printInfo topMargin])/scale, 5349 headerFooterWidth, [self _headerHeight]); 5350 5351 [self _drawHeaderInRect:headerRect]; 5352 [self _drawFooterInRect:footerRect]; 5353} 5354@end 5355 5356@implementation WebView (WebDebugBinding) 5357 5358- (void)addObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context 5359{ 5360 LOG (Bindings, "addObserver:%p forKeyPath:%@ options:%x context:%p", anObserver, keyPath, options, context); 5361 [super addObserver:anObserver forKeyPath:keyPath options:options context:context]; 5362} 5363 5364- (void)removeObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath 5365{ 5366 LOG (Bindings, "removeObserver:%p forKeyPath:%@", anObserver, keyPath); 5367 [super removeObserver:anObserver forKeyPath:keyPath]; 5368} 5369 5370@end 5371 5372//========================================================================================== 5373// Editing 5374 5375@implementation WebView (WebViewCSS) 5376 5377- (DOMCSSStyleDeclaration *)computedStyleForElement:(DOMElement *)element pseudoElement:(NSString *)pseudoElement 5378{ 5379 // FIXME: is this the best level for this conversion? 5380 if (pseudoElement == nil) 5381 pseudoElement = @""; 5382 5383 return [[element ownerDocument] getComputedStyle:element pseudoElement:pseudoElement]; 5384} 5385 5386@end 5387 5388@implementation WebView (WebViewEditing) 5389 5390- (DOMRange *)editableDOMRangeForPoint:(NSPoint)point 5391{ 5392 Page* page = core(self); 5393 if (!page) 5394 return nil; 5395 return kit(page->mainFrame()->editor().rangeForPoint(IntPoint([self convertPoint:point toView:nil])).get()); 5396} 5397 5398- (BOOL)_shouldChangeSelectedDOMRange:(DOMRange *)currentRange toDOMRange:(DOMRange *)proposedRange affinity:(NSSelectionAffinity)selectionAffinity stillSelecting:(BOOL)flag 5399{ 5400 // 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 5401 if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_APERTURE_QUIRK) && [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.Aperture"]) 5402 return YES; 5403 return [[self _editingDelegateForwarder] webView:self shouldChangeSelectedDOMRange:currentRange toDOMRange:proposedRange affinity:selectionAffinity stillSelecting:flag]; 5404} 5405 5406- (BOOL)maintainsInactiveSelection 5407{ 5408 return NO; 5409} 5410 5411- (void)setSelectedDOMRange:(DOMRange *)range affinity:(NSSelectionAffinity)selectionAffinity 5412{ 5413 Frame* coreFrame = core([self _selectedOrMainFrame]); 5414 if (!coreFrame) 5415 return; 5416 5417 if (range == nil) 5418 coreFrame->selection()->clear(); 5419 else { 5420 // Derive the frame to use from the range passed in. 5421 // Using _selectedOrMainFrame could give us a different document than 5422 // the one the range uses. 5423 coreFrame = core([range startContainer])->document()->frame(); 5424 if (!coreFrame) 5425 return; 5426 5427 coreFrame->selection()->setSelectedRange(core(range), core(selectionAffinity), true); 5428 } 5429} 5430 5431- (DOMRange *)selectedDOMRange 5432{ 5433 Frame* coreFrame = core([self _selectedOrMainFrame]); 5434 if (!coreFrame) 5435 return nil; 5436 return kit(coreFrame->selection()->toNormalizedRange().get()); 5437} 5438 5439- (NSSelectionAffinity)selectionAffinity 5440{ 5441 Frame* coreFrame = core([self _selectedOrMainFrame]); 5442 if (!coreFrame) 5443 return NSSelectionAffinityDownstream; 5444 return kit(coreFrame->selection()->affinity()); 5445} 5446 5447- (void)setEditable:(BOOL)flag 5448{ 5449 if ([self isEditable] != flag && _private->page) { 5450 _private->page->setEditable(flag); 5451 if (!_private->tabKeyCyclesThroughElementsChanged) 5452 _private->page->setTabKeyCyclesThroughElements(!flag); 5453 Frame* mainFrame = [self _mainCoreFrame]; 5454 if (mainFrame) { 5455 if (flag) { 5456 mainFrame->editor().applyEditingStyleToBodyElement(); 5457 // If the WebView is made editable and the selection is empty, set it to something. 5458 if (![self selectedDOMRange]) 5459 mainFrame->selection()->setSelectionFromNone(); 5460 } 5461 } 5462 } 5463} 5464 5465- (BOOL)isEditable 5466{ 5467 return _private->page && _private->page->isEditable(); 5468} 5469 5470- (void)setTypingStyle:(DOMCSSStyleDeclaration *)style 5471{ 5472 // We don't know enough at thls level to pass in a relevant WebUndoAction; we'd have to 5473 // change the API to allow this. 5474 [[self _selectedOrMainFrame] _setTypingStyle:style withUndoAction:EditActionUnspecified]; 5475} 5476 5477- (DOMCSSStyleDeclaration *)typingStyle 5478{ 5479 return [[self _selectedOrMainFrame] _typingStyle]; 5480} 5481 5482- (void)setSmartInsertDeleteEnabled:(BOOL)flag 5483{ 5484 if (_private->page->settings()->smartInsertDeleteEnabled() != flag) { 5485 _private->page->settings()->setSmartInsertDeleteEnabled(flag); 5486 [[NSUserDefaults standardUserDefaults] setBool:_private->page->settings()->smartInsertDeleteEnabled() forKey:WebSmartInsertDeleteEnabled]; 5487 [self setSelectTrailingWhitespaceEnabled:!flag]; 5488 } 5489} 5490 5491- (BOOL)smartInsertDeleteEnabled 5492{ 5493 return _private->page->settings()->smartInsertDeleteEnabled(); 5494} 5495 5496- (void)setContinuousSpellCheckingEnabled:(BOOL)flag 5497{ 5498 if (continuousSpellCheckingEnabled != flag) { 5499 continuousSpellCheckingEnabled = flag; 5500 [[NSUserDefaults standardUserDefaults] setBool:continuousSpellCheckingEnabled forKey:WebContinuousSpellCheckingEnabled]; 5501 } 5502 5503 if ([self isContinuousSpellCheckingEnabled]) { 5504 [[self class] _preflightSpellChecker]; 5505 } else { 5506 [[self mainFrame] _unmarkAllMisspellings]; 5507 } 5508} 5509 5510- (BOOL)isContinuousSpellCheckingEnabled 5511{ 5512 return (continuousSpellCheckingEnabled && [self _continuousCheckingAllowed]); 5513} 5514 5515- (NSInteger)spellCheckerDocumentTag 5516{ 5517 if (!_private->hasSpellCheckerDocumentTag) { 5518 _private->spellCheckerDocumentTag = [NSSpellChecker uniqueSpellDocumentTag]; 5519 _private->hasSpellCheckerDocumentTag = YES; 5520 } 5521 return _private->spellCheckerDocumentTag; 5522} 5523 5524- (NSUndoManager *)undoManager 5525{ 5526 if (!_private->allowsUndo) 5527 return nil; 5528 5529 NSUndoManager *undoManager = [[self _editingDelegateForwarder] undoManagerForWebView:self]; 5530 if (undoManager) 5531 return undoManager; 5532 5533 return [super undoManager]; 5534} 5535 5536- (void)registerForEditingDelegateNotification:(NSString *)name selector:(SEL)selector 5537{ 5538 NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter]; 5539 if ([_private->editingDelegate respondsToSelector:selector]) 5540 [defaultCenter addObserver:_private->editingDelegate selector:selector name:name object:self]; 5541} 5542 5543- (void)setEditingDelegate:(id)delegate 5544{ 5545 if (_private->editingDelegate == delegate) 5546 return; 5547 5548 NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter]; 5549 5550 // remove notifications from current delegate 5551 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidBeginEditingNotification object:self]; 5552 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidChangeNotification object:self]; 5553 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidEndEditingNotification object:self]; 5554 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidChangeTypingStyleNotification object:self]; 5555 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidChangeSelectionNotification object:self]; 5556 5557 _private->editingDelegate = delegate; 5558 [_private->editingDelegateForwarder release]; 5559 _private->editingDelegateForwarder = nil; 5560 5561 // add notifications for new delegate 5562 [self registerForEditingDelegateNotification:WebViewDidBeginEditingNotification selector:@selector(webViewDidBeginEditing:)]; 5563 [self registerForEditingDelegateNotification:WebViewDidChangeNotification selector:@selector(webViewDidChange:)]; 5564 [self registerForEditingDelegateNotification:WebViewDidEndEditingNotification selector:@selector(webViewDidEndEditing:)]; 5565 [self registerForEditingDelegateNotification:WebViewDidChangeTypingStyleNotification selector:@selector(webViewDidChangeTypingStyle:)]; 5566 [self registerForEditingDelegateNotification:WebViewDidChangeSelectionNotification selector:@selector(webViewDidChangeSelection:)]; 5567} 5568 5569- (id)editingDelegate 5570{ 5571 return _private->editingDelegate; 5572} 5573 5574- (DOMCSSStyleDeclaration *)styleDeclarationWithText:(NSString *)text 5575{ 5576 // FIXME: Should this really be attached to the document with the current selection? 5577 DOMCSSStyleDeclaration *decl = [[[self _selectedOrMainFrame] DOMDocument] createCSSStyleDeclaration]; 5578 [decl setCssText:text]; 5579 return decl; 5580} 5581 5582@end 5583 5584@implementation WebView (WebViewGrammarChecking) 5585 5586// FIXME: This method should be merged into WebViewEditing when we're not in API freeze 5587- (BOOL)isGrammarCheckingEnabled 5588{ 5589 return grammarCheckingEnabled; 5590} 5591 5592// FIXME: This method should be merged into WebViewEditing when we're not in API freeze 5593- (void)setGrammarCheckingEnabled:(BOOL)flag 5594{ 5595 if (grammarCheckingEnabled == flag) 5596 return; 5597 5598 grammarCheckingEnabled = flag; 5599 [[NSUserDefaults standardUserDefaults] setBool:grammarCheckingEnabled forKey:WebGrammarCheckingEnabled]; 5600 [[NSSpellChecker sharedSpellChecker] updatePanels]; 5601 5602 // We call _preflightSpellChecker when turning continuous spell checking on, but we don't need to do that here 5603 // because grammar checking only occurs on code paths that already preflight spell checking appropriately. 5604 5605 if (![self isGrammarCheckingEnabled]) 5606 [[self mainFrame] _unmarkAllBadGrammar]; 5607} 5608 5609// FIXME: This method should be merged into WebIBActions when we're not in API freeze 5610- (void)toggleGrammarChecking:(id)sender 5611{ 5612 [self setGrammarCheckingEnabled:![self isGrammarCheckingEnabled]]; 5613} 5614 5615@end 5616 5617@implementation WebView (WebViewTextChecking) 5618 5619- (BOOL)isAutomaticQuoteSubstitutionEnabled 5620{ 5621 return automaticQuoteSubstitutionEnabled; 5622} 5623 5624- (BOOL)isAutomaticLinkDetectionEnabled 5625{ 5626 return automaticLinkDetectionEnabled; 5627} 5628 5629- (BOOL)isAutomaticDashSubstitutionEnabled 5630{ 5631 return automaticDashSubstitutionEnabled; 5632} 5633 5634- (BOOL)isAutomaticTextReplacementEnabled 5635{ 5636 return automaticTextReplacementEnabled; 5637} 5638 5639- (BOOL)isAutomaticSpellingCorrectionEnabled 5640{ 5641 return automaticSpellingCorrectionEnabled; 5642} 5643 5644- (void)setAutomaticQuoteSubstitutionEnabled:(BOOL)flag 5645{ 5646 if (automaticQuoteSubstitutionEnabled == flag) 5647 return; 5648 automaticQuoteSubstitutionEnabled = flag; 5649 [[NSUserDefaults standardUserDefaults] setBool:automaticQuoteSubstitutionEnabled forKey:WebAutomaticQuoteSubstitutionEnabled]; 5650 [[NSSpellChecker sharedSpellChecker] updatePanels]; 5651} 5652 5653- (void)toggleAutomaticQuoteSubstitution:(id)sender 5654{ 5655 [self setAutomaticQuoteSubstitutionEnabled:![self isAutomaticQuoteSubstitutionEnabled]]; 5656} 5657 5658- (void)setAutomaticLinkDetectionEnabled:(BOOL)flag 5659{ 5660 if (automaticLinkDetectionEnabled == flag) 5661 return; 5662 automaticLinkDetectionEnabled = flag; 5663 [[NSUserDefaults standardUserDefaults] setBool:automaticLinkDetectionEnabled forKey:WebAutomaticLinkDetectionEnabled]; 5664 [[NSSpellChecker sharedSpellChecker] updatePanels]; 5665} 5666 5667- (void)toggleAutomaticLinkDetection:(id)sender 5668{ 5669 [self setAutomaticLinkDetectionEnabled:![self isAutomaticLinkDetectionEnabled]]; 5670} 5671 5672- (void)setAutomaticDashSubstitutionEnabled:(BOOL)flag 5673{ 5674 if (automaticDashSubstitutionEnabled == flag) 5675 return; 5676 automaticDashSubstitutionEnabled = flag; 5677 [[NSUserDefaults standardUserDefaults] setBool:automaticDashSubstitutionEnabled forKey:WebAutomaticDashSubstitutionEnabled]; 5678 [[NSSpellChecker sharedSpellChecker] updatePanels]; 5679} 5680 5681- (void)toggleAutomaticDashSubstitution:(id)sender 5682{ 5683 [self setAutomaticDashSubstitutionEnabled:![self isAutomaticDashSubstitutionEnabled]]; 5684} 5685 5686- (void)setAutomaticTextReplacementEnabled:(BOOL)flag 5687{ 5688 if (automaticTextReplacementEnabled == flag) 5689 return; 5690 automaticTextReplacementEnabled = flag; 5691 [[NSUserDefaults standardUserDefaults] setBool:automaticTextReplacementEnabled forKey:WebAutomaticTextReplacementEnabled]; 5692 [[NSSpellChecker sharedSpellChecker] updatePanels]; 5693} 5694 5695- (void)toggleAutomaticTextReplacement:(id)sender 5696{ 5697 [self setAutomaticTextReplacementEnabled:![self isAutomaticTextReplacementEnabled]]; 5698} 5699 5700- (void)setAutomaticSpellingCorrectionEnabled:(BOOL)flag 5701{ 5702 if (automaticSpellingCorrectionEnabled == flag) 5703 return; 5704 automaticSpellingCorrectionEnabled = flag; 5705 [[NSUserDefaults standardUserDefaults] setBool:automaticSpellingCorrectionEnabled forKey:WebAutomaticSpellingCorrectionEnabled]; 5706 [[NSSpellChecker sharedSpellChecker] updatePanels]; 5707} 5708 5709- (void)toggleAutomaticSpellingCorrection:(id)sender 5710{ 5711 [self setAutomaticSpellingCorrectionEnabled:![self isAutomaticSpellingCorrectionEnabled]]; 5712} 5713 5714@end 5715 5716@implementation WebView (WebViewUndoableEditing) 5717 5718- (void)replaceSelectionWithNode:(DOMNode *)node 5719{ 5720 [[self _selectedOrMainFrame] _replaceSelectionWithNode:node selectReplacement:YES smartReplace:NO matchStyle:NO]; 5721} 5722 5723- (void)replaceSelectionWithText:(NSString *)text 5724{ 5725 [[self _selectedOrMainFrame] _replaceSelectionWithText:text selectReplacement:YES smartReplace:NO]; 5726} 5727 5728- (void)replaceSelectionWithMarkupString:(NSString *)markupString 5729{ 5730 [[self _selectedOrMainFrame] _replaceSelectionWithMarkupString:markupString baseURLString:nil selectReplacement:YES smartReplace:NO]; 5731} 5732 5733- (void)replaceSelectionWithArchive:(WebArchive *)archive 5734{ 5735 [[[self _selectedOrMainFrame] _dataSource] _replaceSelectionWithArchive:archive selectReplacement:YES]; 5736} 5737 5738- (void)deleteSelection 5739{ 5740 WebFrame *webFrame = [self _selectedOrMainFrame]; 5741 Frame* coreFrame = core(webFrame); 5742 if (coreFrame) 5743 coreFrame->editor().deleteSelectionWithSmartDelete([(WebHTMLView *)[[webFrame frameView] documentView] _canSmartCopyOrDelete]); 5744} 5745 5746- (void)applyStyle:(DOMCSSStyleDeclaration *)style 5747{ 5748 // We don't know enough at thls level to pass in a relevant WebUndoAction; we'd have to 5749 // change the API to allow this. 5750 WebFrame *webFrame = [self _selectedOrMainFrame]; 5751 Frame* coreFrame = core(webFrame); 5752 // FIXME: We shouldn't have to make a copy here. 5753 if (coreFrame) 5754 coreFrame->editor().applyStyle(core(style)->copyProperties().get()); 5755} 5756 5757@end 5758 5759@implementation WebView (WebViewEditingActions) 5760 5761- (void)_performResponderOperation:(SEL)selector with:(id)parameter 5762{ 5763 static BOOL reentered = NO; 5764 if (reentered) { 5765 [[self nextResponder] tryToPerform:selector with:parameter]; 5766 return; 5767 } 5768 5769 // There are two possibilities here. 5770 // 5771 // One is that WebView has been called in its role as part of the responder chain. 5772 // In that case, it's fine to call the first responder and end up calling down the 5773 // responder chain again. Later we will return here with reentered = YES and continue 5774 // past the WebView. 5775 // 5776 // The other is that we are being called directly, in which case we want to pass the 5777 // selector down to the view inside us that can handle it, and continue down the 5778 // responder chain as usual. 5779 5780 // Pass this selector down to the first responder. 5781 NSResponder *responder = [self _responderForResponderOperations]; 5782 reentered = YES; 5783 [responder tryToPerform:selector with:parameter]; 5784 reentered = NO; 5785} 5786 5787#define FORWARD(name) \ 5788 - (void)name:(id)sender { [self _performResponderOperation:_cmd with:sender]; } 5789 5790FOR_EACH_RESPONDER_SELECTOR(FORWARD) 5791 5792- (void)insertText:(NSString *)text 5793{ 5794 [self _performResponderOperation:_cmd with:text]; 5795} 5796 5797- (NSDictionary *)typingAttributes 5798{ 5799 Frame* coreFrame = core([self _selectedOrMainFrame]); 5800 if (coreFrame) 5801 return coreFrame->editor().fontAttributesForSelectionStart(); 5802 5803 return nil; 5804} 5805 5806 5807@end 5808 5809@implementation WebView (WebViewEditingInMail) 5810 5811- (void)_insertNewlineInQuotedContent 5812{ 5813 [[self _selectedOrMainFrame] _insertParagraphSeparatorInQuotedContent]; 5814} 5815 5816- (void)_replaceSelectionWithNode:(DOMNode *)node matchStyle:(BOOL)matchStyle 5817{ 5818 [[self _selectedOrMainFrame] _replaceSelectionWithNode:node selectReplacement:YES smartReplace:NO matchStyle:matchStyle]; 5819} 5820 5821- (BOOL)_selectionIsCaret 5822{ 5823 Frame* coreFrame = core([self _selectedOrMainFrame]); 5824 if (!coreFrame) 5825 return NO; 5826 return coreFrame->selection()->isCaret(); 5827} 5828 5829- (BOOL)_selectionIsAll 5830{ 5831 Frame* coreFrame = core([self _selectedOrMainFrame]); 5832 if (!coreFrame) 5833 return NO; 5834 return coreFrame->selection()->isAll(CanCrossEditingBoundary); 5835} 5836 5837- (void)_simplifyMarkup:(DOMNode *)startNode endNode:(DOMNode *)endNode 5838{ 5839 Frame* coreFrame = core([self mainFrame]); 5840 if (!coreFrame || !startNode) 5841 return; 5842 Node* coreStartNode= core(startNode); 5843 if (coreStartNode->document() != coreFrame->document()) 5844 return; 5845 return coreFrame->editor().simplifyMarkup(coreStartNode, core(endNode)); 5846} 5847 5848@end 5849 5850static WebFrameView *containingFrameView(NSView *view) 5851{ 5852 while (view && ![view isKindOfClass:[WebFrameView class]]) 5853 view = [view superview]; 5854 return (WebFrameView *)view; 5855} 5856 5857@implementation WebView (WebFileInternal) 5858 5859- (float)_deviceScaleFactor 5860{ 5861 if (_private->customDeviceScaleFactor != 0) 5862 return _private->customDeviceScaleFactor; 5863 5864 NSWindow *window = [self window]; 5865 NSWindow *hostWindow = [self hostWindow]; 5866#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 5867 if (window) 5868 return [window backingScaleFactor]; 5869 if (hostWindow) 5870 return [hostWindow backingScaleFactor]; 5871 return [[NSScreen mainScreen] backingScaleFactor]; 5872#else 5873 if (window) 5874 return [window userSpaceScaleFactor]; 5875 if (hostWindow) 5876 return [hostWindow userSpaceScaleFactor]; 5877 return [[NSScreen mainScreen] userSpaceScaleFactor]; 5878#endif 5879} 5880 5881static inline uint64_t roundUpToPowerOf2(uint64_t num) 5882{ 5883 return powf(2.0, ceilf(log2f(num))); 5884} 5885 5886+ (void)_setCacheModel:(WebCacheModel)cacheModel 5887{ 5888 if (s_didSetCacheModel && cacheModel == s_cacheModel) 5889 return; 5890 5891 NSString *nsurlCacheDirectory = (NSString *)HardAutorelease(WKCopyFoundationCacheDirectory()); 5892 if (!nsurlCacheDirectory) 5893 nsurlCacheDirectory = NSHomeDirectory(); 5894 5895 static uint64_t memSize = roundUpToPowerOf2(WebMemorySize() / 1024 / 1024); 5896 unsigned long long diskFreeSize = WebVolumeFreeSize(nsurlCacheDirectory) / 1024 / 1000; 5897 NSURLCache *nsurlCache = [NSURLCache sharedURLCache]; 5898 5899 unsigned cacheTotalCapacity = 0; 5900 unsigned cacheMinDeadCapacity = 0; 5901 unsigned cacheMaxDeadCapacity = 0; 5902 double deadDecodedDataDeletionInterval = 0; 5903 5904 unsigned pageCacheCapacity = 0; 5905 5906 NSUInteger nsurlCacheMemoryCapacity = 0; 5907 NSUInteger nsurlCacheDiskCapacity = 0; 5908 5909 switch (cacheModel) { 5910 case WebCacheModelDocumentViewer: { 5911 // Page cache capacity (in pages) 5912 pageCacheCapacity = 0; 5913 5914 // Object cache capacities (in bytes) 5915 if (memSize >= 4096) 5916 cacheTotalCapacity = 128 * 1024 * 1024; 5917 else if (memSize >= 2048) 5918 cacheTotalCapacity = 96 * 1024 * 1024; 5919 else if (memSize >= 1024) 5920 cacheTotalCapacity = 32 * 1024 * 1024; 5921 else if (memSize >= 512) 5922 cacheTotalCapacity = 16 * 1024 * 1024; 5923 5924 cacheMinDeadCapacity = 0; 5925 cacheMaxDeadCapacity = 0; 5926 5927 // Foundation memory cache capacity (in bytes) 5928 nsurlCacheMemoryCapacity = 0; 5929 5930 // Foundation disk cache capacity (in bytes) 5931 nsurlCacheDiskCapacity = [nsurlCache diskCapacity]; 5932 5933 break; 5934 } 5935 case WebCacheModelDocumentBrowser: { 5936 // Page cache capacity (in pages) 5937 if (memSize >= 1024) 5938 pageCacheCapacity = 3; 5939 else if (memSize >= 512) 5940 pageCacheCapacity = 2; 5941 else if (memSize >= 256) 5942 pageCacheCapacity = 1; 5943 else 5944 pageCacheCapacity = 0; 5945 5946 // Object cache capacities (in bytes) 5947 if (memSize >= 4096) 5948 cacheTotalCapacity = 128 * 1024 * 1024; 5949 else if (memSize >= 2048) 5950 cacheTotalCapacity = 96 * 1024 * 1024; 5951 else if (memSize >= 1024) 5952 cacheTotalCapacity = 32 * 1024 * 1024; 5953 else if (memSize >= 512) 5954 cacheTotalCapacity = 16 * 1024 * 1024; 5955 5956 cacheMinDeadCapacity = cacheTotalCapacity / 8; 5957 cacheMaxDeadCapacity = cacheTotalCapacity / 4; 5958 5959 // Foundation memory cache capacity (in bytes) 5960 if (memSize >= 2048) 5961 nsurlCacheMemoryCapacity = 4 * 1024 * 1024; 5962 else if (memSize >= 1024) 5963 nsurlCacheMemoryCapacity = 2 * 1024 * 1024; 5964 else if (memSize >= 512) 5965 nsurlCacheMemoryCapacity = 1 * 1024 * 1024; 5966 else 5967 nsurlCacheMemoryCapacity = 512 * 1024; 5968 5969 // Foundation disk cache capacity (in bytes) 5970 if (diskFreeSize >= 16384) 5971 nsurlCacheDiskCapacity = 50 * 1024 * 1024; 5972 else if (diskFreeSize >= 8192) 5973 nsurlCacheDiskCapacity = 40 * 1024 * 1024; 5974 else if (diskFreeSize >= 4096) 5975 nsurlCacheDiskCapacity = 30 * 1024 * 1024; 5976 else 5977 nsurlCacheDiskCapacity = 20 * 1024 * 1024; 5978 5979 break; 5980 } 5981 case WebCacheModelPrimaryWebBrowser: { 5982 // Page cache capacity (in pages) 5983 // (Research indicates that value / page drops substantially after 3 pages.) 5984 if (memSize >= 2048) 5985 pageCacheCapacity = 5; 5986 else if (memSize >= 1024) 5987 pageCacheCapacity = 4; 5988 else if (memSize >= 512) 5989 pageCacheCapacity = 3; 5990 else if (memSize >= 256) 5991 pageCacheCapacity = 2; 5992 else 5993 pageCacheCapacity = 1; 5994 5995 // Object cache capacities (in bytes) 5996 // (Testing indicates that value / MB depends heavily on content and 5997 // browsing pattern. Even growth above 128MB can have substantial 5998 // value / MB for some content / browsing patterns.) 5999 if (memSize >= 4096) 6000 cacheTotalCapacity = 192 * 1024 * 1024; 6001 else if (memSize >= 2048) 6002 cacheTotalCapacity = 128 * 1024 * 1024; 6003 else if (memSize >= 1024) 6004 cacheTotalCapacity = 64 * 1024 * 1024; 6005 else if (memSize >= 512) 6006 cacheTotalCapacity = 32 * 1024 * 1024; 6007 6008 cacheMinDeadCapacity = cacheTotalCapacity / 4; 6009 cacheMaxDeadCapacity = cacheTotalCapacity / 2; 6010 6011 // This code is here to avoid a PLT regression. We can remove it if we 6012 // can prove that the overall system gain would justify the regression. 6013 cacheMaxDeadCapacity = max(24u, cacheMaxDeadCapacity); 6014 6015 deadDecodedDataDeletionInterval = 60; 6016 6017 // Foundation memory cache capacity (in bytes) 6018 // (These values are small because WebCore does most caching itself.) 6019 if (memSize >= 1024) 6020 nsurlCacheMemoryCapacity = 4 * 1024 * 1024; 6021 else if (memSize >= 512) 6022 nsurlCacheMemoryCapacity = 2 * 1024 * 1024; 6023 else if (memSize >= 256) 6024 nsurlCacheMemoryCapacity = 1 * 1024 * 1024; 6025 else 6026 nsurlCacheMemoryCapacity = 512 * 1024; 6027 6028 // Foundation disk cache capacity (in bytes) 6029 if (diskFreeSize >= 16384) 6030 nsurlCacheDiskCapacity = 175 * 1024 * 1024; 6031 else if (diskFreeSize >= 8192) 6032 nsurlCacheDiskCapacity = 150 * 1024 * 1024; 6033 else if (diskFreeSize >= 4096) 6034 nsurlCacheDiskCapacity = 125 * 1024 * 1024; 6035 else if (diskFreeSize >= 2048) 6036 nsurlCacheDiskCapacity = 100 * 1024 * 1024; 6037 else if (diskFreeSize >= 1024) 6038 nsurlCacheDiskCapacity = 75 * 1024 * 1024; 6039 else 6040 nsurlCacheDiskCapacity = 50 * 1024 * 1024; 6041 6042 break; 6043 } 6044 default: 6045 ASSERT_NOT_REACHED(); 6046 }; 6047 6048 6049 // Don't shrink a big disk cache, since that would cause churn. 6050 nsurlCacheDiskCapacity = max(nsurlCacheDiskCapacity, [nsurlCache diskCapacity]); 6051 6052 memoryCache()->setCapacities(cacheMinDeadCapacity, cacheMaxDeadCapacity, cacheTotalCapacity); 6053 memoryCache()->setDeadDecodedDataDeletionInterval(deadDecodedDataDeletionInterval); 6054 pageCache()->setCapacity(pageCacheCapacity); 6055 [nsurlCache setMemoryCapacity:nsurlCacheMemoryCapacity]; 6056 [nsurlCache setDiskCapacity:nsurlCacheDiskCapacity]; 6057 6058 s_cacheModel = cacheModel; 6059 s_didSetCacheModel = YES; 6060} 6061 6062+ (WebCacheModel)_cacheModel 6063{ 6064 return s_cacheModel; 6065} 6066 6067+ (WebCacheModel)_didSetCacheModel 6068{ 6069 return s_didSetCacheModel; 6070} 6071 6072+ (WebCacheModel)_maxCacheModelInAnyInstance 6073{ 6074 WebCacheModel cacheModel = WebCacheModelDocumentViewer; 6075 NSEnumerator *enumerator = [(NSMutableSet *)allWebViewsSet objectEnumerator]; 6076 while (WebPreferences *preferences = [[enumerator nextObject] preferences]) 6077 cacheModel = max(cacheModel, [preferences cacheModel]); 6078 return cacheModel; 6079} 6080 6081+ (void)_cacheModelChangedNotification:(NSNotification *)notification 6082{ 6083 WebPreferences *preferences = (WebPreferences *)[notification object]; 6084 ASSERT([preferences isKindOfClass:[WebPreferences class]]); 6085 6086 WebCacheModel cacheModel = [preferences cacheModel]; 6087 if (![self _didSetCacheModel] || cacheModel > [self _cacheModel]) 6088 [self _setCacheModel:cacheModel]; 6089 else if (cacheModel < [self _cacheModel]) 6090 [self _setCacheModel:max([[WebPreferences standardPreferences] cacheModel], [self _maxCacheModelInAnyInstance])]; 6091} 6092 6093+ (void)_preferencesRemovedNotification:(NSNotification *)notification 6094{ 6095 WebPreferences *preferences = (WebPreferences *)[notification object]; 6096 ASSERT([preferences isKindOfClass:[WebPreferences class]]); 6097 6098 if ([preferences cacheModel] == [self _cacheModel]) 6099 [self _setCacheModel:max([[WebPreferences standardPreferences] cacheModel], [self _maxCacheModelInAnyInstance])]; 6100} 6101 6102- (WebFrame *)_focusedFrame 6103{ 6104 NSResponder *resp = [[self window] firstResponder]; 6105 if (resp && [resp isKindOfClass:[NSView class]] && [(NSView *)resp isDescendantOf:[[self mainFrame] frameView]]) { 6106 WebFrameView *frameView = containingFrameView((NSView *)resp); 6107 ASSERT(frameView != nil); 6108 return [frameView webFrame]; 6109 } 6110 6111 return nil; 6112} 6113 6114- (BOOL)_isLoading 6115{ 6116 WebFrame *mainFrame = [self mainFrame]; 6117 return [[mainFrame _dataSource] isLoading] 6118 || [[mainFrame provisionalDataSource] isLoading]; 6119} 6120 6121- (WebFrameView *)_frameViewAtWindowPoint:(NSPoint)point 6122{ 6123 if (_private->closed) 6124 return nil; 6125 NSView *view = [self hitTest:[[self superview] convertPoint:point fromView:nil]]; 6126 if (![view isDescendantOf:[[self mainFrame] frameView]]) 6127 return nil; 6128 WebFrameView *frameView = containingFrameView(view); 6129 ASSERT(frameView); 6130 return frameView; 6131} 6132 6133+ (void)_preflightSpellCheckerNow:(id)sender 6134{ 6135 [[NSSpellChecker sharedSpellChecker] _preflightChosenSpellServer]; 6136} 6137 6138+ (void)_preflightSpellChecker 6139{ 6140 // As AppKit does, we wish to delay tickling the shared spellchecker into existence on application launch. 6141 if ([NSSpellChecker sharedSpellCheckerExists]) { 6142 [self _preflightSpellCheckerNow:self]; 6143 } else { 6144 [self performSelector:@selector(_preflightSpellCheckerNow:) withObject:self afterDelay:2.0]; 6145 } 6146} 6147 6148- (BOOL)_continuousCheckingAllowed 6149{ 6150 static BOOL allowContinuousSpellChecking = YES; 6151 static BOOL readAllowContinuousSpellCheckingDefault = NO; 6152 if (!readAllowContinuousSpellCheckingDefault) { 6153 if ([[NSUserDefaults standardUserDefaults] objectForKey:@"NSAllowContinuousSpellChecking"]) { 6154 allowContinuousSpellChecking = [[NSUserDefaults standardUserDefaults] boolForKey:@"NSAllowContinuousSpellChecking"]; 6155 } 6156 readAllowContinuousSpellCheckingDefault = YES; 6157 } 6158 return allowContinuousSpellChecking; 6159} 6160 6161- (NSResponder *)_responderForResponderOperations 6162{ 6163 NSResponder *responder = [[self window] firstResponder]; 6164 WebFrameView *mainFrameView = [[self mainFrame] frameView]; 6165 6166 // If the current responder is outside of the webview, use our main frameView or its 6167 // document view. We also do this for subviews of self that are siblings of the main 6168 // frameView since clients might insert non-webview-related views there (see 4552713). 6169 if (responder != self && ![mainFrameView _web_firstResponderIsSelfOrDescendantView]) { 6170 responder = [mainFrameView documentView]; 6171 if (!responder) 6172 responder = mainFrameView; 6173 } 6174 return responder; 6175} 6176 6177- (void)_openFrameInNewWindowFromMenu:(NSMenuItem *)sender 6178{ 6179 ASSERT_ARG(sender, [sender isKindOfClass:[NSMenuItem class]]); 6180 6181 NSDictionary *element = [sender representedObject]; 6182 ASSERT([element isKindOfClass:[NSDictionary class]]); 6183 6184 WebDataSource *dataSource = [(WebFrame *)[element objectForKey:WebElementFrameKey] dataSource]; 6185 NSURLRequest *request = [[dataSource request] copy]; 6186 ASSERT(request); 6187 6188 [self _openNewWindowWithRequest:request]; 6189 [request release]; 6190} 6191 6192- (void)_searchWithGoogleFromMenu:(id)sender 6193{ 6194 id documentView = [[[self selectedFrame] frameView] documentView]; 6195 if (![documentView conformsToProtocol:@protocol(WebDocumentText)]) { 6196 return; 6197 } 6198 6199 NSString *selectedString = [(id <WebDocumentText>)documentView selectedString]; 6200 if ([selectedString length] == 0) { 6201 return; 6202 } 6203 6204 NSPasteboard *pasteboard = [NSPasteboard pasteboardWithUniqueName]; 6205 [pasteboard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil]; 6206 NSMutableString *s = [selectedString mutableCopy]; 6207 const unichar nonBreakingSpaceCharacter = 0xA0; 6208 NSString *nonBreakingSpaceString = [NSString stringWithCharacters:&nonBreakingSpaceCharacter length:1]; 6209 [s replaceOccurrencesOfString:nonBreakingSpaceString withString:@" " options:0 range:NSMakeRange(0, [s length])]; 6210 [pasteboard setString:s forType:NSStringPboardType]; 6211 [s release]; 6212 6213 // FIXME: seems fragile to use the service by name, but this is what AppKit does 6214 NSPerformService(@"Search With Google", pasteboard); 6215} 6216 6217- (void)_searchWithSpotlightFromMenu:(id)sender 6218{ 6219 id documentView = [[[self selectedFrame] frameView] documentView]; 6220 if (![documentView conformsToProtocol:@protocol(WebDocumentText)]) 6221 return; 6222 6223 NSString *selectedString = [(id <WebDocumentText>)documentView selectedString]; 6224 if (![selectedString length]) 6225 return; 6226 6227 [[NSWorkspace sharedWorkspace] showSearchResultsForQueryString:selectedString]; 6228} 6229 6230#if USE(GLIB) 6231- (void)_clearGlibLoopObserver 6232{ 6233 if (!_private->glibRunLoopObserver) 6234 return; 6235 6236 CFRunLoopObserverInvalidate(_private->glibRunLoopObserver); 6237 CFRelease(_private->glibRunLoopObserver); 6238 _private->glibRunLoopObserver = 0; 6239} 6240#endif 6241@end 6242 6243@implementation WebView (WebViewInternal) 6244 6245+ (BOOL)shouldIncludeInWebKitStatistics 6246{ 6247 return NO; 6248} 6249 6250- (BOOL)_becomingFirstResponderFromOutside 6251{ 6252 return _private->becomingFirstResponderFromOutside; 6253} 6254 6255#if ENABLE(ICONDATABASE) 6256- (void)_receivedIconChangedNotification:(NSNotification *)notification 6257{ 6258 // Get the URL for this notification 6259 NSDictionary *userInfo = [notification userInfo]; 6260 ASSERT([userInfo isKindOfClass:[NSDictionary class]]); 6261 NSString *urlString = [userInfo objectForKey:WebIconNotificationUserInfoURLKey]; 6262 ASSERT([urlString isKindOfClass:[NSString class]]); 6263 6264 // If that URL matches the current main frame, dispatch the delegate call, which will also unregister 6265 // us for this notification 6266 if ([[self mainFrameURL] isEqualTo:urlString]) 6267 [self _dispatchDidReceiveIconFromWebFrame:[self mainFrame]]; 6268} 6269 6270- (void)_registerForIconNotification:(BOOL)listen 6271{ 6272 if (listen) 6273 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_receivedIconChangedNotification:) name:WebIconDatabaseDidAddIconNotification object:nil]; 6274 else 6275 [[NSNotificationCenter defaultCenter] removeObserver:self name:WebIconDatabaseDidAddIconNotification object:nil]; 6276} 6277 6278- (void)_dispatchDidReceiveIconFromWebFrame:(WebFrame *)webFrame 6279{ 6280 // FIXME: This willChangeValueForKey call is too late, because the icon has already changed by now. 6281 [self _willChangeValueForKey:_WebMainFrameIconKey]; 6282 6283 // 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 6284 // notification any longer 6285 [self _registerForIconNotification:NO]; 6286 6287 WebFrameLoadDelegateImplementationCache* cache = &_private->frameLoadDelegateImplementations; 6288 if (cache->didReceiveIconForFrameFunc) { 6289 Image* image = iconDatabase().synchronousIconForPageURL(core(webFrame)->document()->url().string(), IntSize(16, 16)); 6290 if (NSImage *icon = webGetNSImage(image, NSMakeSize(16, 16))) 6291 CallFrameLoadDelegate(cache->didReceiveIconForFrameFunc, self, @selector(webView:didReceiveIcon:forFrame:), icon, webFrame); 6292 } 6293 6294 [self _didChangeValueForKey:_WebMainFrameIconKey]; 6295} 6296#endif // ENABLE(ICONDATABASE) 6297 6298- (void)_addObject:(id)object forIdentifier:(unsigned long)identifier 6299{ 6300 ASSERT(!_private->identifierMap.contains(identifier)); 6301 6302 // If the identifier map is initially empty it means we're starting a load 6303 // of something. The semantic is that the web view should be around as long 6304 // as something is loading. Because of that we retain the web view. 6305 if (_private->identifierMap.isEmpty()) 6306 CFRetain(self); 6307 6308 _private->identifierMap.set(identifier, object); 6309} 6310 6311- (id)_objectForIdentifier:(unsigned long)identifier 6312{ 6313 return _private->identifierMap.get(identifier).get(); 6314} 6315 6316- (void)_removeObjectForIdentifier:(unsigned long)identifier 6317{ 6318 ASSERT(_private->identifierMap.contains(identifier)); 6319 _private->identifierMap.remove(identifier); 6320 6321 // If the identifier map is now empty it means we're no longer loading anything 6322 // and we should release the web view. Autorelease rather than release in order to 6323 // avoid re-entering this method beneath -dealloc with the same identifier. <rdar://problem/10523721> 6324 if (_private->identifierMap.isEmpty()) 6325 [self autorelease]; 6326} 6327 6328- (void)_retrieveKeyboardUIModeFromPreferences:(NSNotification *)notification 6329{ 6330 CFPreferencesAppSynchronize(UniversalAccessDomain); 6331 6332 Boolean keyExistsAndHasValidFormat; 6333 int mode = CFPreferencesGetAppIntegerValue(AppleKeyboardUIMode, UniversalAccessDomain, &keyExistsAndHasValidFormat); 6334 6335 // The keyboard access mode is reported by two bits: 6336 // Bit 0 is set if feature is on 6337 // Bit 1 is set if full keyboard access works for any control, not just text boxes and lists 6338 _private->_keyboardUIMode = (mode & 0x2) ? KeyboardAccessFull : KeyboardAccessDefault; 6339 6340 // check for tabbing to links 6341 if ([_private->preferences tabsToLinks]) 6342 _private->_keyboardUIMode = (KeyboardUIMode)(_private->_keyboardUIMode | KeyboardAccessTabsToLinks); 6343} 6344 6345- (KeyboardUIMode)_keyboardUIMode 6346{ 6347 if (!_private->_keyboardUIModeAccessed) { 6348 _private->_keyboardUIModeAccessed = YES; 6349 6350 [self _retrieveKeyboardUIModeFromPreferences:nil]; 6351 6352 [[NSDistributedNotificationCenter defaultCenter] 6353 addObserver:self selector:@selector(_retrieveKeyboardUIModeFromPreferences:) 6354 name:KeyboardUIModeDidChangeNotification object:nil]; 6355 6356 [[NSNotificationCenter defaultCenter] 6357 addObserver:self selector:@selector(_retrieveKeyboardUIModeFromPreferences:) 6358 name:WebPreferencesChangedInternalNotification object:nil]; 6359 } 6360 return _private->_keyboardUIMode; 6361} 6362 6363- (void)_setInsertionPasteboard:(NSPasteboard *)pasteboard 6364{ 6365 _private->insertionPasteboard = pasteboard; 6366} 6367 6368- (Frame*)_mainCoreFrame 6369{ 6370 return (_private && _private->page) ? _private->page->mainFrame() : 0; 6371} 6372 6373- (WebFrame *)_selectedOrMainFrame 6374{ 6375 WebFrame *result = [self selectedFrame]; 6376 if (result == nil) 6377 result = [self mainFrame]; 6378 return result; 6379} 6380 6381#if USE(ACCELERATED_COMPOSITING) 6382 6383- (BOOL)_needsOneShotDrawingSynchronization 6384{ 6385 return _private->needsOneShotDrawingSynchronization; 6386} 6387 6388- (void)_setNeedsOneShotDrawingSynchronization:(BOOL)needsSynchronization 6389{ 6390 _private->needsOneShotDrawingSynchronization = needsSynchronization; 6391} 6392 6393- (BOOL)_flushCompositingChanges 6394{ 6395 Frame* frame = [self _mainCoreFrame]; 6396 if (frame && frame->view()) 6397 return frame->view()->flushCompositingStateIncludingSubframes(); 6398 6399 return YES; 6400} 6401 6402/* 6403 The order of events with compositing updates is this: 6404 6405 Start of runloop End of runloop 6406 | | 6407 --|-------------------------------------------------------|-- 6408 ^ ^ ^ 6409 | | | 6410 NSWindow update, | CA commit 6411 NSView drawing | 6412 flush | 6413 layerSyncRunLoopObserverCallBack 6414 6415 To avoid flashing, we have to ensure that compositing changes (rendered via 6416 the CoreAnimation rendering display link) appear on screen at the same time 6417 as content painted into the window via the normal WebCore rendering path. 6418 6419 CoreAnimation will commit any layer changes at the end of the runloop via 6420 its "CA commit" observer. Those changes can then appear onscreen at any time 6421 when the display link fires, which can result in unsynchronized rendering. 6422 6423 To fix this, the GraphicsLayerCA code in WebCore does not change the CA 6424 layer tree during style changes and layout; it stores up all changes and 6425 commits them via flushCompositingState(). There are then two situations in 6426 which we can call flushCompositingState(): 6427 6428 1. When painting. FrameView::paintContents() makes a call to flushCompositingState(). 6429 6430 2. When style changes/layout have made changes to the layer tree which do not 6431 result in painting. In this case we need a run loop observer to do a 6432 flushCompositingState() at an appropriate time. The observer will keep firing 6433 until the time is right (essentially when there are no more pending layouts). 6434 6435*/ 6436bool LayerFlushController::flushLayers() 6437{ 6438 NSWindow *window = [m_webView window]; 6439 6440 // An NSWindow may not display in the next runloop cycle after dirtying due to delayed window display logic, 6441 // in which case this observer can fire first. So if the window is due for a display, don't commit 6442 // layer changes, otherwise they'll show on screen before the view drawing. 6443 bool viewsNeedDisplay; 6444#ifndef __LP64__ 6445 if (window && [window _wrapsCarbonWindow]) 6446 viewsNeedDisplay = HIViewGetNeedsDisplay(HIViewGetRoot(static_cast<WindowRef>([window windowRef]))); 6447 else 6448#endif 6449 viewsNeedDisplay = [window viewsNeedDisplay]; 6450 6451 if (viewsNeedDisplay) 6452 return false; 6453 6454 [m_webView _viewWillDrawInternal]; 6455 6456 if ([m_webView _flushCompositingChanges]) { 6457 // AppKit may have disabled screen updates, thinking an upcoming window flush will re-enable them. 6458 // In case setNeedsDisplayInRect() has prevented the window from needing to be flushed, re-enable screen 6459 // updates here. 6460 if (![window isFlushWindowDisabled]) 6461 [window _enableScreenUpdatesIfNeeded]; 6462 6463 return true; 6464 } 6465 6466 return false; 6467} 6468 6469- (void)_scheduleCompositingLayerFlush 6470{ 6471 if (!_private->layerFlushController) 6472 _private->layerFlushController = LayerFlushController::create(self); 6473 _private->layerFlushController->scheduleLayerFlush(); 6474} 6475 6476#endif 6477 6478#if ENABLE(VIDEO) 6479 6480- (void)_enterFullscreenForNode:(WebCore::Node*)node 6481{ 6482 ASSERT(node->hasTagName(WebCore::HTMLNames::videoTag)); 6483 HTMLMediaElement* videoElement = toMediaElement(node); 6484 6485 if (_private->fullscreenController) { 6486 if ([_private->fullscreenController mediaElement] == videoElement) { 6487 // The backend may just warn us that the underlaying plaftormMovie() 6488 // has changed. Just force an update. 6489 [_private->fullscreenController setMediaElement:videoElement]; 6490 return; // No more to do. 6491 } 6492 6493 // First exit Fullscreen for the old mediaElement. 6494 [_private->fullscreenController mediaElement]->exitFullscreen(); 6495 // This previous call has to trigger _exitFullscreen, 6496 // which has to clear _private->fullscreenController. 6497 ASSERT(!_private->fullscreenController); 6498 } 6499 if (!_private->fullscreenController) { 6500 _private->fullscreenController = [[WebVideoFullscreenController alloc] init]; 6501 [_private->fullscreenController setMediaElement:videoElement]; 6502 [_private->fullscreenController enterFullscreen:[[self window] screen]]; 6503 } 6504 else 6505 [_private->fullscreenController setMediaElement:videoElement]; 6506} 6507 6508- (void)_exitFullscreen 6509{ 6510 if (!_private->fullscreenController) 6511 return; 6512 [_private->fullscreenController exitFullscreen]; 6513 [_private->fullscreenController release]; 6514 _private->fullscreenController = nil; 6515} 6516 6517#endif 6518 6519#if ENABLE(FULLSCREEN_API) 6520- (BOOL)_supportsFullScreenForElement:(const WebCore::Element*)element withKeyboard:(BOOL)withKeyboard 6521{ 6522 if (![[WebPreferences standardPreferences] fullScreenEnabled]) 6523 return NO; 6524 6525 return !withKeyboard; 6526} 6527 6528- (void)_enterFullScreenForElement:(WebCore::Element*)element 6529{ 6530 if (!_private->newFullscreenController) 6531 _private->newFullscreenController = [[WebFullScreenController alloc] init]; 6532 6533 [_private->newFullscreenController setElement:element]; 6534 [_private->newFullscreenController setWebView:self]; 6535 [_private->newFullscreenController enterFullScreen:[[self window] screen]]; 6536} 6537 6538- (void)_exitFullScreenForElement:(WebCore::Element*)element 6539{ 6540 if (!_private->newFullscreenController) 6541 return; 6542 [_private->newFullscreenController exitFullScreen]; 6543} 6544#endif 6545 6546#if USE(GLIB) 6547 6548static void glibContextIterationCallback(CFRunLoopObserverRef, CFRunLoopActivity, void*) 6549{ 6550 g_main_context_iteration(0, FALSE); 6551} 6552 6553- (void)_scheduleGlibContextIterations 6554{ 6555 if (_private->glibRunLoopObserver) 6556 return; 6557 6558 NSRunLoop* myRunLoop = [NSRunLoop currentRunLoop]; 6559 6560 // Create a run loop observer and attach it to the run loop. 6561 CFRunLoopObserverContext context = {0, self, 0, 0, 0}; 6562 _private->glibRunLoopObserver = CFRunLoopObserverCreate(kCFAllocatorDefault, kCFRunLoopBeforeWaiting, YES, 0, &glibContextIterationCallback, &context); 6563 6564 if (_private->glibRunLoopObserver) { 6565 CFRunLoopRef cfLoop = [myRunLoop getCFRunLoop]; 6566 CFRunLoopAddObserver(cfLoop, _private->glibRunLoopObserver, kCFRunLoopDefaultMode); 6567 } 6568 6569} 6570#endif 6571 6572#if USE(AUTOCORRECTION_PANEL) 6573- (void)handleAcceptedAlternativeText:(NSString*)text 6574{ 6575 WebFrame *webFrame = [self _selectedOrMainFrame]; 6576 Frame* coreFrame = core(webFrame); 6577 if (coreFrame) 6578 coreFrame->editor().handleAlternativeTextUIResult(text); 6579} 6580#endif 6581 6582#if USE(DICTATION_ALTERNATIVES) 6583- (void)_getWebCoreDictationAlternatives:(Vector<DictationAlternative>&)alternatives fromTextAlternatives:(const Vector<TextAlternativeWithRange>&)alternativesWithRange 6584{ 6585 for (size_t i = 0; i < alternativesWithRange.size(); ++i) { 6586 const TextAlternativeWithRange& alternativeWithRange = alternativesWithRange[i]; 6587 uint64_t dictationContext = _private->m_alternativeTextUIController->addAlternatives(alternativeWithRange.alternatives); 6588 if (dictationContext) 6589 alternatives.append(DictationAlternative(alternativeWithRange.range.location, alternativeWithRange.range.length, dictationContext)); 6590 } 6591} 6592 6593- (void)_showDictationAlternativeUI:(const WebCore::FloatRect&)boundingBoxOfDictatedText forDictationContext:(uint64_t)dictationContext 6594{ 6595 _private->m_alternativeTextUIController->showAlternatives(self, [self _convertRectFromRootView:boundingBoxOfDictatedText], dictationContext, ^(NSString* acceptedAlternative) { 6596 [self handleAcceptedAlternativeText:acceptedAlternative]; 6597 }); 6598} 6599 6600- (void)_removeDictationAlternatives:(uint64_t)dictationContext 6601{ 6602 _private->m_alternativeTextUIController->removeAlternatives(dictationContext); 6603} 6604 6605- (Vector<String>)_dictationAlternatives:(uint64_t)dictationContext 6606{ 6607 return _private->m_alternativeTextUIController->alternativesForContext(dictationContext); 6608} 6609#endif 6610 6611- (NSPoint)_convertPointFromRootView:(NSPoint)point 6612{ 6613 return NSMakePoint(point.x, [self bounds].size.height - point.y); 6614} 6615 6616- (NSRect)_convertRectFromRootView:(NSRect)rect 6617{ 6618 return NSMakeRect(rect.origin.x, [self bounds].size.height - rect.origin.y - rect.size.height, rect.size.width, rect.size.height); 6619} 6620 6621@end 6622 6623@implementation WebView (WebViewDeviceOrientation) 6624 6625- (void)_setDeviceOrientationProvider:(id<WebDeviceOrientationProvider>)deviceOrientationProvider 6626{ 6627 if (_private) 6628 _private->m_deviceOrientationProvider = deviceOrientationProvider; 6629} 6630 6631- (id<WebDeviceOrientationProvider>)_deviceOrientationProvider 6632{ 6633 if (_private) 6634 return _private->m_deviceOrientationProvider; 6635 return nil; 6636} 6637 6638@end 6639 6640@implementation WebView (WebViewGeolocation) 6641 6642- (void)_setGeolocationProvider:(id<WebGeolocationProvider>)geolocationProvider 6643{ 6644 if (_private) 6645 _private->_geolocationProvider = geolocationProvider; 6646} 6647 6648- (id<WebGeolocationProvider>)_geolocationProvider 6649{ 6650 if (_private) 6651 return _private->_geolocationProvider; 6652 return nil; 6653} 6654 6655- (void)_geolocationDidChangePosition:(WebGeolocationPosition *)position 6656{ 6657#if ENABLE(GEOLOCATION) 6658 if (_private && _private->page) 6659 WebCore::GeolocationController::from(_private->page)->positionChanged(core(position)); 6660#endif // ENABLE(GEOLOCATION) 6661} 6662 6663- (void)_geolocationDidFailWithMessage:(NSString *)errorMessage 6664{ 6665#if ENABLE(GEOLOCATION) 6666 if (_private && _private->page) { 6667 RefPtr<GeolocationError> geolocatioError = GeolocationError::create(GeolocationError::PositionUnavailable, errorMessage); 6668 WebCore::GeolocationController::from(_private->page)->errorOccurred(geolocatioError.get()); 6669 } 6670#endif // ENABLE(GEOLOCATION) 6671} 6672 6673@end 6674 6675@implementation WebView (WebViewNotification) 6676- (void)_setNotificationProvider:(id<WebNotificationProvider>)notificationProvider 6677{ 6678 if (_private && !_private->_notificationProvider) { 6679 _private->_notificationProvider = notificationProvider; 6680 [_private->_notificationProvider registerWebView:self]; 6681 } 6682} 6683 6684- (id<WebNotificationProvider>)_notificationProvider 6685{ 6686 if (_private) 6687 return _private->_notificationProvider; 6688 return nil; 6689} 6690 6691- (void)_notificationDidShow:(uint64_t)notificationID 6692{ 6693 [[self _notificationProvider] webView:self didShowNotification:notificationID]; 6694} 6695 6696- (void)_notificationDidClick:(uint64_t)notificationID 6697{ 6698 [[self _notificationProvider] webView:self didClickNotification:notificationID]; 6699} 6700 6701- (void)_notificationsDidClose:(NSArray *)notificationIDs 6702{ 6703 [[self _notificationProvider] webView:self didCloseNotifications:notificationIDs]; 6704} 6705 6706- (uint64_t)_notificationIDForTesting:(JSValueRef)jsNotification 6707{ 6708#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS) 6709 JSContextRef context = [[self mainFrame] globalContext]; 6710 WebCore::Notification* notification = toNotification(toJS(toJS(context), jsNotification)); 6711 return static_cast<WebNotificationClient*>(NotificationController::clientFrom(_private->page))->notificationIDForTesting(notification); 6712#else 6713 return 0; 6714#endif 6715} 6716@end 6717 6718@implementation WebView (WebViewFullScreen) 6719 6720- (NSView*)fullScreenPlaceholderView 6721{ 6722#if ENABLE(FULLSCREEN_API) 6723 if (_private->newFullscreenController && [_private->newFullscreenController isFullScreen]) 6724 return [_private->newFullscreenController webViewPlaceholder]; 6725#endif 6726 return nil; 6727} 6728 6729@end 6730 6731void WebInstallMemoryPressureHandler(void) 6732{ 6733 memoryPressureHandler().install(); 6734} 6735