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