1/* 2 * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of Apple Inc. ("Apple") nor the names of 14 * its contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#import "WebFrameInternal.h" 30 31#import "DOMCSSStyleDeclarationInternal.h" 32#import "DOMDocumentFragmentInternal.h" 33#import "DOMDocumentInternal.h" 34#import "DOMElementInternal.h" 35#import "DOMHTMLElementInternal.h" 36#import "DOMNodeInternal.h" 37#import "DOMRangeInternal.h" 38#import "WebArchiveInternal.h" 39#import "WebChromeClient.h" 40#import "WebDataSourceInternal.h" 41#import "WebDocumentLoaderMac.h" 42#import "WebDynamicScrollBarsView.h" 43#import "WebElementDictionary.h" 44#import "WebFrameLoaderClient.h" 45#import "WebFrameViewInternal.h" 46#import "WebHTMLView.h" 47#import "WebHTMLViewInternal.h" 48#import "WebKitStatisticsPrivate.h" 49#import "WebKitVersionChecks.h" 50#import "WebNSObjectExtras.h" 51#import "WebNSURLExtras.h" 52#import "WebScriptDebugger.h" 53#import "WebScriptWorldInternal.h" 54#import "WebViewInternal.h" 55#import <JavaScriptCore/APICast.h> 56#import <JavaScriptCore/JSContextInternal.h> 57#import <WebCore/AXObjectCache.h> 58#import <WebCore/AccessibilityObject.h> 59#import <WebCore/AnimationController.h> 60#import <WebCore/CSSStyleDeclaration.h> 61#import <WebCore/CachedResourceLoader.h> 62#import <WebCore/Chrome.h> 63#import <WebCore/ColorMac.h> 64#import <WebCore/DOMImplementation.h> 65#import <WebCore/DatabaseManager.h> 66#import <WebCore/DocumentFragment.h> 67#import <WebCore/DocumentLoader.h> 68#import <WebCore/DocumentMarkerController.h> 69#import <WebCore/Editor.h> 70#import <WebCore/EventHandler.h> 71#import <WebCore/EventNames.h> 72#import <WebCore/FrameLoadRequest.h> 73#import <WebCore/FrameLoader.h> 74#import <WebCore/FrameLoaderStateMachine.h> 75#import <WebCore/FrameTree.h> 76#import <WebCore/GraphicsContext.h> 77#import <WebCore/HTMLFrameOwnerElement.h> 78#import <WebCore/HTMLNames.h> 79#import <WebCore/HistoryItem.h> 80#import <WebCore/HitTestResult.h> 81#import <WebCore/JSNode.h> 82#import <WebCore/LegacyWebArchive.h> 83#import <WebCore/MainFrame.h> 84#import <WebCore/Page.h> 85#import <WebCore/PlatformEventFactoryMac.h> 86#import <WebCore/PluginData.h> 87#import <WebCore/PrintContext.h> 88#import <WebCore/RenderView.h> 89#import <WebCore/RenderWidget.h> 90#import <WebCore/RuntimeApplicationChecks.h> 91#import <WebCore/ScriptController.h> 92#import <WebCore/SecurityOrigin.h> 93#import <WebCore/SmartReplace.h> 94#import <WebCore/StyleProperties.h> 95#import <WebCore/SubframeLoader.h> 96#import <WebCore/TextIterator.h> 97#import <WebCore/ThreadCheck.h> 98#import <WebCore/VisibleUnits.h> 99#import <WebCore/htmlediting.h> 100#import <WebCore/markup.h> 101#import <WebKitSystemInterface.h> 102#import <bindings/ScriptValue.h> 103#import <runtime/JSLock.h> 104#import <runtime/JSObject.h> 105#import <runtime/JSCJSValue.h> 106#import <wtf/CurrentTime.h> 107 108#if PLATFORM(IOS) 109#import "WebMailDelegate.h" 110#import "WebResource.h" 111#import "WebUIKitDelegate.h" 112#import <WebCore/Document.h> 113#import <WebCore/Editor.h> 114#import <WebCore/EditorClient.h> 115#import <WebCore/FocusController.h> 116#import <WebCore/FrameSelection.h> 117#import <WebCore/HistoryController.h> 118#import <WebCore/NodeTraversal.h> 119#import <WebCore/RenderLayer.h> 120#import <WebCore/SimpleFontData.h> 121#import <WebCore/TextResourceDecoder.h> 122#import <WebCore/WAKScrollView.h> 123#import <WebCore/WAKViewPrivate.h> 124#import <WebCore/WKGraphics.h> 125#import <WebCore/WebCoreThreadRun.h> 126#endif 127 128#if USE(QUICK_LOOK) 129#import <WebCore/QuickLook.h> 130#import <WebCore/WebCoreURLResponseIOS.h> 131#endif 132 133using namespace WebCore; 134using namespace HTMLNames; 135 136using JSC::JSGlobalObject; 137using JSC::JSLock; 138 139/* 140Here is the current behavior matrix for four types of navigations: 141 142Standard Nav: 143 144 Restore form state: YES 145 Restore scroll and focus state: YES 146 Cache policy: NSURLRequestUseProtocolCachePolicy 147 Add to back/forward list: YES 148 149Back/Forward: 150 151 Restore form state: YES 152 Restore scroll and focus state: YES 153 Cache policy: NSURLRequestReturnCacheDataElseLoad 154 Add to back/forward list: NO 155 156Reload (meaning only the reload button): 157 158 Restore form state: NO 159 Restore scroll and focus state: YES 160 Cache policy: NSURLRequestReloadIgnoringCacheData 161 Add to back/forward list: NO 162 163Repeat load of the same URL (by any other means of navigation other than the reload button, including hitting return in the location field): 164 165 Restore form state: NO 166 Restore scroll and focus state: NO, reset to initial conditions 167 Cache policy: NSURLRequestReloadIgnoringCacheData 168 Add to back/forward list: NO 169*/ 170 171NSString *WebPageCacheEntryDateKey = @"WebPageCacheEntryDateKey"; 172NSString *WebPageCacheDataSourceKey = @"WebPageCacheDataSourceKey"; 173NSString *WebPageCacheDocumentViewKey = @"WebPageCacheDocumentViewKey"; 174 175NSString *WebFrameMainDocumentError = @"WebFrameMainDocumentErrorKey"; 176NSString *WebFrameHasPlugins = @"WebFrameHasPluginsKey"; 177NSString *WebFrameHasUnloadListener = @"WebFrameHasUnloadListenerKey"; 178NSString *WebFrameUsesDatabases = @"WebFrameUsesDatabasesKey"; 179NSString *WebFrameUsesGeolocation = @"WebFrameUsesGeolocationKey"; 180NSString *WebFrameUsesApplicationCache = @"WebFrameUsesApplicationCacheKey"; 181NSString *WebFrameCanSuspendActiveDOMObjects = @"WebFrameCanSuspendActiveDOMObjectsKey"; 182 183// FIXME: Remove when this key becomes publicly defined 184NSString *NSAccessibilityEnhancedUserInterfaceAttribute = @"AXEnhancedUserInterface"; 185 186@implementation WebFramePrivate 187 188- (void)dealloc 189{ 190 [webFrameView release]; 191 192 [super dealloc]; 193} 194 195- (void)finalize 196{ 197 [super finalize]; 198} 199 200- (void)setWebFrameView:(WebFrameView *)v 201{ 202 [v retain]; 203 [webFrameView release]; 204 webFrameView = v; 205} 206 207@end 208 209EditableLinkBehavior core(WebKitEditableLinkBehavior editableLinkBehavior) 210{ 211 switch (editableLinkBehavior) { 212 case WebKitEditableLinkDefaultBehavior: 213 return EditableLinkDefaultBehavior; 214 case WebKitEditableLinkAlwaysLive: 215 return EditableLinkAlwaysLive; 216 case WebKitEditableLinkOnlyLiveWithShiftKey: 217 return EditableLinkOnlyLiveWithShiftKey; 218 case WebKitEditableLinkLiveWhenNotFocused: 219 return EditableLinkLiveWhenNotFocused; 220 case WebKitEditableLinkNeverLive: 221 return EditableLinkNeverLive; 222 } 223 ASSERT_NOT_REACHED(); 224 return EditableLinkDefaultBehavior; 225} 226 227TextDirectionSubmenuInclusionBehavior core(WebTextDirectionSubmenuInclusionBehavior behavior) 228{ 229 switch (behavior) { 230 case WebTextDirectionSubmenuNeverIncluded: 231 return TextDirectionSubmenuNeverIncluded; 232 case WebTextDirectionSubmenuAutomaticallyIncluded: 233 return TextDirectionSubmenuAutomaticallyIncluded; 234 case WebTextDirectionSubmenuAlwaysIncluded: 235 return TextDirectionSubmenuAlwaysIncluded; 236 } 237 ASSERT_NOT_REACHED(); 238 return TextDirectionSubmenuNeverIncluded; 239} 240 241#if PLATFORM(IOS) 242PassOwnPtr<Vector<Vector<String>>> vectorForDictationPhrasesArray(NSArray *dictationPhrases) 243{ 244 NSUInteger dictationPhrasesCount = [dictationPhrases count]; 245 if (!dictationPhrasesCount) 246 return PassOwnPtr<Vector<Vector<String> > >(); 247 248 OwnPtr<Vector<Vector<String> > > dictationPhrasesVector = adoptPtr(new Vector<Vector<String> >(dictationPhrasesCount)); 249 250 for (NSUInteger i = 0; i < dictationPhrasesCount; i++) { 251 252 id dictationPhrase = [dictationPhrases objectAtIndex:i]; 253 if (![dictationPhrase isKindOfClass:[NSArray class]]) 254 continue; 255 256 NSArray *interpretationsArray = (NSArray *)dictationPhrase; 257 Vector<String>& interpretationsVector = dictationPhrasesVector->at(i); 258 259 NSUInteger interpretationsCount = [interpretationsArray count]; 260 261 for (NSUInteger j = 0; j < interpretationsCount; j++) { 262 263 id interpretation = [interpretationsArray objectAtIndex:j]; 264 if (![interpretation isKindOfClass:[NSString class]]) 265 continue; 266 267 interpretationsVector.append(String((NSString *)interpretation)); 268 } 269 } 270 271 return dictationPhrasesVector.release(); 272} 273#endif 274 275@implementation WebFrame (WebInternal) 276 277Frame* core(WebFrame *frame) 278{ 279 return frame ? frame->_private->coreFrame : 0; 280} 281 282WebFrame *kit(Frame* frame) 283{ 284 if (!frame) 285 return nil; 286 287 FrameLoaderClient& frameLoaderClient = frame->loader().client(); 288 if (frameLoaderClient.isEmptyFrameLoaderClient()) 289 return nil; 290 291 return static_cast<WebFrameLoaderClient&>(frameLoaderClient).webFrame(); 292} 293 294Page* core(WebView *webView) 295{ 296 return [webView page]; 297} 298 299WebView *kit(Page* page) 300{ 301 if (!page) 302 return nil; 303 304 if (page->chrome().client().isEmptyChromeClient()) 305 return nil; 306 307 return static_cast<WebChromeClient&>(page->chrome().client()).webView(); 308} 309 310WebView *getWebView(WebFrame *webFrame) 311{ 312 Frame* coreFrame = core(webFrame); 313 if (!coreFrame) 314 return nil; 315 return kit(coreFrame->page()); 316} 317 318+ (PassRefPtr<Frame>)_createFrameWithPage:(Page*)page frameName:(const String&)name frameView:(WebFrameView *)frameView ownerElement:(HTMLFrameOwnerElement*)ownerElement 319{ 320 WebView *webView = kit(page); 321 322 WebFrame *frame = [[self alloc] _initWithWebFrameView:frameView webView:webView]; 323 RefPtr<Frame> coreFrame = Frame::create(page, ownerElement, new WebFrameLoaderClient(frame)); 324 [frame release]; 325 frame->_private->coreFrame = coreFrame.get(); 326 327 coreFrame->tree().setName(name); 328 if (ownerElement) { 329 ASSERT(ownerElement->document().frame()); 330 ownerElement->document().frame()->tree().appendChild(coreFrame.get()); 331 } 332 333 coreFrame->init(); 334 335 [webView _setZoomMultiplier:[webView _realZoomMultiplier] isTextOnly:[webView _realZoomMultiplierIsTextOnly]]; 336 337 return coreFrame.release(); 338} 339 340+ (void)_createMainFrameWithPage:(Page*)page frameName:(const String&)name frameView:(WebFrameView *)frameView 341{ 342 WebView *webView = kit(page); 343 344 WebFrame *frame = [[self alloc] _initWithWebFrameView:frameView webView:webView]; 345 frame->_private->coreFrame = &page->mainFrame(); 346 static_cast<WebFrameLoaderClient&>(page->mainFrame().loader().client()).setWebFrame(frame); 347 [frame release]; 348 349 page->mainFrame().tree().setName(name); 350 page->mainFrame().init(); 351 352 [webView _setZoomMultiplier:[webView _realZoomMultiplier] isTextOnly:[webView _realZoomMultiplierIsTextOnly]]; 353} 354 355+ (PassRefPtr<WebCore::Frame>)_createSubframeWithOwnerElement:(HTMLFrameOwnerElement*)ownerElement frameName:(const String&)name frameView:(WebFrameView *)frameView 356{ 357 return [self _createFrameWithPage:ownerElement->document().frame()->page() frameName:name frameView:frameView ownerElement:ownerElement]; 358} 359 360- (BOOL)_isIncludedInWebKitStatistics 361{ 362 return _private && _private->includedInWebKitStatistics; 363} 364 365#if PLATFORM(IOS) 366static NSURL *createUniqueWebDataURL(); 367 368+ (void)_createMainFrameWithSimpleHTMLDocumentWithPage:(Page*)page frameView:(WebFrameView *)frameView style:(NSString *)style 369{ 370 WebView *webView = kit(page); 371 372 WebFrame *frame = [[self alloc] _initWithWebFrameView:frameView webView:webView]; 373 frame->_private->coreFrame = &page->mainFrame(); 374 static_cast<WebFrameLoaderClient&>(page->mainFrame().loader().client()).setWebFrame(frame); 375 [frame release]; 376 377 frame->_private->coreFrame->initWithSimpleHTMLDocument(style, createUniqueWebDataURL()); 378} 379#endif 380 381- (void)_attachScriptDebugger 382{ 383 ScriptController& scriptController = _private->coreFrame->script(); 384 385 // Calling ScriptController::globalObject() would create a window shell, and dispatch corresponding callbacks, which may be premature 386 // if the script debugger is attached before a document is created. These calls use the debuggerWorld(), we will need to pass a world 387 // to be able to debug isolated worlds. 388 if (!scriptController.existingWindowShell(debuggerWorld())) 389 return; 390 391 JSGlobalObject* globalObject = scriptController.globalObject(debuggerWorld()); 392 if (!globalObject) 393 return; 394 395 if (_private->scriptDebugger) { 396 ASSERT(_private->scriptDebugger.get() == globalObject->debugger()); 397 return; 398 } 399 400 _private->scriptDebugger = std::make_unique<WebScriptDebugger>(globalObject); 401} 402 403- (void)_detachScriptDebugger 404{ 405 _private->scriptDebugger = nullptr; 406} 407 408- (id)_initWithWebFrameView:(WebFrameView *)fv webView:(WebView *)v 409{ 410 self = [super init]; 411 if (!self) 412 return nil; 413 414 _private = [[WebFramePrivate alloc] init]; 415 416 // Set includedInWebKitStatistics before calling WebFrameView _setWebFrame, since 417 // it calls WebFrame _isIncludedInWebKitStatistics. 418 if ((_private->includedInWebKitStatistics = [[v class] shouldIncludeInWebKitStatistics])) 419 ++WebFrameCount; 420 421 if (fv) { 422 [_private setWebFrameView:fv]; 423 [fv _setWebFrame:self]; 424 } 425 426 _private->shouldCreateRenderers = YES; 427 428 return self; 429} 430 431- (void)_clearCoreFrame 432{ 433 _private->coreFrame = 0; 434} 435 436- (void)_updateBackgroundAndUpdatesWhileOffscreen 437{ 438 WebView *webView = getWebView(self); 439 BOOL drawsBackground = [webView drawsBackground]; 440#if !PLATFORM(IOS) 441 NSColor *backgroundColor = [webView backgroundColor]; 442#else 443 CGColorRef backgroundColor = [webView backgroundColor]; 444#endif 445 446 Frame* coreFrame = _private->coreFrame; 447 for (Frame* frame = coreFrame; frame; frame = frame->tree().traverseNext(coreFrame)) { 448 // Don't call setDrawsBackground:YES here because it may be NO because of a load 449 // in progress; WebFrameLoaderClient keeps it set to NO during the load process. 450 WebFrame *webFrame = kit(frame); 451 if (!drawsBackground) 452 [[[webFrame frameView] _scrollView] setDrawsBackground:NO]; 453#if !PLATFORM(IOS) 454 [[[webFrame frameView] _scrollView] setBackgroundColor:backgroundColor]; 455#endif 456 457 if (FrameView* view = frame->view()) { 458 view->setTransparent(!drawsBackground); 459#if !PLATFORM(IOS) 460 Color color = colorFromNSColor([backgroundColor colorUsingColorSpaceName:NSDeviceRGBColorSpace]); 461#else 462 Color color = Color(backgroundColor); 463#endif 464 view->setBaseBackgroundColor(color); 465 view->setShouldUpdateWhileOffscreen([webView shouldUpdateWhileOffscreen]); 466 } 467 } 468} 469 470- (void)_setInternalLoadDelegate:(id)internalLoadDelegate 471{ 472 _private->internalLoadDelegate = internalLoadDelegate; 473} 474 475- (id)_internalLoadDelegate 476{ 477 return _private->internalLoadDelegate; 478} 479 480- (void)_unmarkAllBadGrammar 481{ 482 Frame* coreFrame = _private->coreFrame; 483 for (Frame* frame = coreFrame; frame; frame = frame->tree().traverseNext(coreFrame)) { 484 if (Document* document = frame->document()) 485 document->markers().removeMarkers(DocumentMarker::Grammar); 486 } 487} 488 489- (void)_unmarkAllMisspellings 490{ 491#if !PLATFORM(IOS) 492 Frame* coreFrame = _private->coreFrame; 493 for (Frame* frame = coreFrame; frame; frame = frame->tree().traverseNext(coreFrame)) { 494 if (Document* document = frame->document()) 495 document->markers().removeMarkers(DocumentMarker::Spelling); 496 } 497#endif 498} 499 500- (BOOL)_hasSelection 501{ 502 id documentView = [_private->webFrameView documentView]; 503 504 // optimization for common case to avoid creating potentially large selection string 505 if ([documentView isKindOfClass:[WebHTMLView class]]) 506 if (Frame* coreFrame = _private->coreFrame) 507 return coreFrame->selection().isRange(); 508 509 if ([documentView conformsToProtocol:@protocol(WebDocumentText)]) 510 return [[documentView selectedString] length] > 0; 511 512 return NO; 513} 514 515- (void)_clearSelection 516{ 517 id documentView = [_private->webFrameView documentView]; 518 if ([documentView conformsToProtocol:@protocol(WebDocumentText)]) 519 [documentView deselectAll]; 520} 521 522#if !ASSERT_DISABLED 523- (BOOL)_atMostOneFrameHasSelection 524{ 525 // FIXME: 4186050 is one known case that makes this debug check fail. 526 BOOL found = NO; 527 Frame* coreFrame = _private->coreFrame; 528 for (Frame* frame = coreFrame; frame; frame = frame->tree().traverseNext(coreFrame)) 529 if ([kit(frame) _hasSelection]) { 530 if (found) 531 return NO; 532 found = YES; 533 } 534 return YES; 535} 536#endif 537 538- (WebFrame *)_findFrameWithSelection 539{ 540 Frame* coreFrame = _private->coreFrame; 541 for (Frame* frame = coreFrame; frame; frame = frame->tree().traverseNext(coreFrame)) { 542 WebFrame *webFrame = kit(frame); 543 if ([webFrame _hasSelection]) 544 return webFrame; 545 } 546 return nil; 547} 548 549- (void)_clearSelectionInOtherFrames 550{ 551 // We rely on WebDocumentSelection protocol implementors to call this method when they become first 552 // responder. It would be nicer to just notice first responder changes here instead, but there's no 553 // notification sent when the first responder changes in general (Radar 2573089). 554 WebFrame *frameWithSelection = [[getWebView(self) mainFrame] _findFrameWithSelection]; 555 if (frameWithSelection != self) 556 [frameWithSelection _clearSelection]; 557 558 // While we're in the general area of selection and frames, check that there is only one now. 559 ASSERT([[getWebView(self) mainFrame] _atMostOneFrameHasSelection]); 560} 561 562static inline WebDataSource *dataSource(DocumentLoader* loader) 563{ 564 return loader ? static_cast<WebDocumentLoaderMac*>(loader)->dataSource() : nil; 565} 566 567- (WebDataSource *)_dataSource 568{ 569 return dataSource(_private->coreFrame->loader().documentLoader()); 570} 571 572#if PLATFORM(IOS) 573- (BOOL)_isCommitting 574{ 575 return _private->isCommitting; 576} 577 578- (void)_setIsCommitting:(BOOL)value 579{ 580 _private->isCommitting = value; 581} 582#endif 583 584- (NSArray *)_nodesFromList:(Vector<Node*> *)nodesVector 585{ 586 size_t size = nodesVector->size(); 587 NSMutableArray *nodes = [NSMutableArray arrayWithCapacity:size]; 588 for (size_t i = 0; i < size; ++i) 589 [nodes addObject:kit((*nodesVector)[i])]; 590 return nodes; 591} 592 593- (NSString *)_selectedString 594{ 595 return _private->coreFrame->displayStringModifiedByEncoding(_private->coreFrame->editor().selectedText()); 596} 597 598- (NSString *)_stringForRange:(DOMRange *)range 599{ 600 return plainText(core(range), TextIteratorDefaultBehavior, true); 601} 602 603- (BOOL)_shouldFlattenCompositingLayers:(CGContextRef)context 604{ 605#if !PLATFORM(IOS) 606 // -currentContextDrawingToScreen returns YES for bitmap contexts. 607 BOOL isPrinting = ![NSGraphicsContext currentContextDrawingToScreen]; 608 if (isPrinting) 609 return YES; 610#endif 611 612 if (!WKCGContextIsBitmapContext(context)) 613 return NO; 614 615 // If we're drawing into a bitmap, we might be snapshotting, or drawing into a layer-backed view. 616 id documentView = [_private->webFrameView documentView]; 617 if ([documentView isKindOfClass:[WebHTMLView class]] && [(WebHTMLView *)documentView _web_isDrawingIntoLayer]) 618 return NO; 619 620 return [getWebView(self) _includesFlattenedCompositingLayersWhenDrawingToBitmap]; 621} 622 623- (void)_drawRect:(NSRect)rect contentsOnly:(BOOL)contentsOnly 624{ 625#if !PLATFORM(IOS) 626 ASSERT([[NSGraphicsContext currentContext] isFlipped]); 627 628 CGContextRef ctx = static_cast<CGContextRef>([[NSGraphicsContext currentContext] graphicsPort]); 629#else 630 CGContextRef ctx = WKGetCurrentGraphicsContext(); 631#endif 632 GraphicsContext context(ctx); 633 634#if PLATFORM(IOS) 635 // FIXME: when <rdar://problem/9034977> is fixed there will be no need to do this here. 636 WebCore::Frame *frame = core(self); 637 if (WebCore::Page* page = frame->page()) 638 context.setIsAcceleratedContext(page->settings().acceleratedDrawingEnabled()); 639#endif 640 641 FrameView* view = _private->coreFrame->view(); 642 643 bool shouldFlatten = false; 644 if (Frame* parentFrame = _private->coreFrame->tree().parent()) { 645 // For subframes, we need to inherit the paint behavior from our parent 646 FrameView* parentView = parentFrame ? parentFrame->view() : 0; 647 if (parentView) 648 shouldFlatten = parentView->paintBehavior() & PaintBehaviorFlattenCompositingLayers; 649 } else 650 shouldFlatten = [self _shouldFlattenCompositingLayers:ctx]; 651 652 PaintBehavior oldBehavior = PaintBehaviorNormal; 653 if (shouldFlatten) { 654 oldBehavior = view->paintBehavior(); 655 view->setPaintBehavior(oldBehavior | PaintBehaviorFlattenCompositingLayers); 656 } 657 658 if (contentsOnly) 659 view->paintContents(&context, enclosingIntRect(rect)); 660 else 661 view->paint(&context, enclosingIntRect(rect)); 662 663 if (shouldFlatten) 664 view->setPaintBehavior(oldBehavior); 665} 666 667- (BOOL)_getVisibleRect:(NSRect*)rect 668{ 669 ASSERT_ARG(rect, rect); 670 if (RenderWidget* ownerRenderer = _private->coreFrame->ownerRenderer()) { 671 if (ownerRenderer->needsLayout()) 672 return NO; 673 *rect = ownerRenderer->pixelSnappedAbsoluteClippedOverflowRect(); 674 return YES; 675 } 676 677 return NO; 678} 679 680- (NSString *)_stringByEvaluatingJavaScriptFromString:(NSString *)string 681{ 682 return [self _stringByEvaluatingJavaScriptFromString:string forceUserGesture:true]; 683} 684 685- (NSString *)_stringByEvaluatingJavaScriptFromString:(NSString *)string forceUserGesture:(BOOL)forceUserGesture 686{ 687 if (!string) 688 return @""; 689 690 ASSERT(_private->coreFrame->document()); 691 RetainPtr<WebFrame> protect(self); // Executing arbitrary JavaScript can destroy the frame. 692 693#if PLATFORM(IOS) 694 ASSERT(WebThreadIsLockedOrDisabled()); 695 JSC::ExecState* exec = _private->coreFrame->script().globalObject(mainThreadNormalWorld())->globalExec(); 696 JSC::JSLockHolder jscLock(exec); 697#endif 698 699 JSC::JSValue result = _private->coreFrame->script().executeScript(string, forceUserGesture).jsValue(); 700 701 if (!_private->coreFrame) // In case the script removed our frame from the page. 702 return @""; 703 704 // This bizarre set of rules matches behavior from WebKit for Safari 2.0. 705 // If you don't like it, use -[WebScriptObject evaluateWebScript:] or 706 // JSEvaluateScript instead, since they have less surprising semantics. 707 if (!result || (!result.isBoolean() && !result.isString() && !result.isNumber())) 708 return @""; 709 710#if !PLATFORM(IOS) 711 JSC::ExecState* exec = _private->coreFrame->script().globalObject(mainThreadNormalWorld())->globalExec(); 712 JSC::JSLockHolder lock(exec); 713#endif 714 return result.toWTFString(exec); 715} 716 717- (NSRect)_caretRectAtPosition:(const Position&)pos affinity:(NSSelectionAffinity)affinity 718{ 719 VisiblePosition visiblePosition(pos, static_cast<EAffinity>(affinity)); 720 return visiblePosition.absoluteCaretBounds(); 721} 722 723- (NSRect)_firstRectForDOMRange:(DOMRange *)range 724{ 725 return _private->coreFrame->editor().firstRectForRange(core(range)); 726} 727 728- (void)_scrollDOMRangeToVisible:(DOMRange *)range 729{ 730 NSRect rangeRect = [self _firstRectForDOMRange:range]; 731 Node *startNode = core([range startContainer]); 732 733 if (startNode && startNode->renderer()) { 734#if !PLATFORM(IOS) 735 startNode->renderer()->scrollRectToVisible(enclosingIntRect(rangeRect), ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded); 736#else 737 RenderLayer* layer = startNode->renderer()->enclosingLayer(); 738 if (layer) { 739 layer->setAdjustForIOSCaretWhenScrolling(true); 740 startNode->renderer()->scrollRectToVisible(enclosingIntRect(rangeRect), ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded); 741 layer->setAdjustForIOSCaretWhenScrolling(false); 742 _private->coreFrame->selection().setCaretRectNeedsUpdate(); 743 _private->coreFrame->selection().updateAppearance(); 744 } 745#endif 746 } 747} 748 749#if PLATFORM(IOS) 750- (void)_scrollDOMRangeToVisible:(DOMRange *)range withInset:(CGFloat)inset 751{ 752 NSRect rangeRect = NSInsetRect([self _firstRectForDOMRange:range], inset, inset); 753 Node *startNode = core([range startContainer]); 754 755 if (startNode && startNode->renderer()) { 756 RenderLayer* layer = startNode->renderer()->enclosingLayer(); 757 if (layer) { 758 layer->setAdjustForIOSCaretWhenScrolling(true); 759 startNode->renderer()->scrollRectToVisible(enclosingIntRect(rangeRect), ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded); 760 layer->setAdjustForIOSCaretWhenScrolling(false); 761 762 Frame *coreFrame = core(self); 763 if (coreFrame) { 764 FrameSelection& frameSelection = coreFrame->selection(); 765 frameSelection.setCaretRectNeedsUpdate(); 766 frameSelection.updateAppearance(); 767 } 768 } 769 } 770} 771#endif 772 773- (BOOL)_needsLayout 774{ 775 return _private->coreFrame->view() ? _private->coreFrame->view()->needsLayout() : false; 776} 777 778#if !PLATFORM(IOS) 779- (DOMRange *)_rangeByAlteringCurrentSelection:(FrameSelection::EAlteration)alteration direction:(SelectionDirection)direction granularity:(TextGranularity)granularity 780{ 781 if (_private->coreFrame->selection().isNone()) 782 return nil; 783 784 FrameSelection selection; 785 selection.setSelection(_private->coreFrame->selection().selection()); 786 selection.modify(alteration, direction, granularity); 787 return kit(selection.toNormalizedRange().get()); 788} 789#endif 790 791- (TextGranularity)_selectionGranularity 792{ 793 return _private->coreFrame->selection().granularity(); 794} 795 796- (NSRange)_convertToNSRange:(Range *)range 797{ 798 if (!range) 799 return NSMakeRange(NSNotFound, 0); 800 801 size_t location; 802 size_t length; 803 if (!TextIterator::getLocationAndLengthFromRange(_private->coreFrame->selection().rootEditableElementOrDocumentElement(), range, location, length)) 804 return NSMakeRange(NSNotFound, 0); 805 806 return NSMakeRange(location, length); 807} 808 809- (PassRefPtr<Range>)_convertToDOMRange:(NSRange)nsrange 810{ 811 if (nsrange.location > INT_MAX) 812 return 0; 813 if (nsrange.length > INT_MAX || nsrange.location + nsrange.length > INT_MAX) 814 nsrange.length = INT_MAX - nsrange.location; 815 816 // our critical assumption is that we are only called by input methods that 817 // concentrate on a given area containing the selection 818 // We have to do this because of text fields and textareas. The DOM for those is not 819 // directly in the document DOM, so serialization is problematic. Our solution is 820 // to use the root editable element of the selection start as the positional base. 821 // That fits with AppKit's idea of an input context. 822 return TextIterator::rangeFromLocationAndLength(_private->coreFrame->selection().rootEditableElementOrDocumentElement(), nsrange.location, nsrange.length); 823} 824 825- (DOMRange *)_convertNSRangeToDOMRange:(NSRange)nsrange 826{ 827 return kit([self _convertToDOMRange:nsrange].get()); 828} 829 830- (NSRange)_convertDOMRangeToNSRange:(DOMRange *)range 831{ 832 return [self _convertToNSRange:core(range)]; 833} 834 835- (DOMRange *)_markDOMRange 836{ 837 return kit(_private->coreFrame->editor().mark().toNormalizedRange().get()); 838} 839 840// Given proposedRange, returns an extended range that includes adjacent whitespace that should 841// be deleted along with the proposed range in order to preserve proper spacing and punctuation of 842// the text surrounding the deletion. 843- (DOMRange *)_smartDeleteRangeForProposedRange:(DOMRange *)proposedRange 844{ 845 Node* startContainer = core([proposedRange startContainer]); 846 Node* endContainer = core([proposedRange endContainer]); 847 if (startContainer == nil || endContainer == nil) 848 return nil; 849 850 ASSERT(&startContainer->document() == &endContainer->document()); 851 852 _private->coreFrame->document()->updateLayoutIgnorePendingStylesheets(); 853 854 Position start = Position(startContainer, [proposedRange startOffset], Position::PositionIsOffsetInAnchor); 855 Position end = Position(endContainer, [proposedRange endOffset], Position::PositionIsOffsetInAnchor); 856 Position newStart = start.upstream().leadingWhitespacePosition(DOWNSTREAM, true); 857 if (newStart.isNull()) 858 newStart = start; 859 Position newEnd = end.downstream().trailingWhitespacePosition(DOWNSTREAM, true); 860 if (newEnd.isNull()) 861 newEnd = end; 862 863 newStart = newStart.parentAnchoredEquivalent(); 864 newEnd = newEnd.parentAnchoredEquivalent(); 865 866 RefPtr<Range> range = _private->coreFrame->document()->createRange(); 867 int exception = 0; 868 range->setStart(newStart.containerNode(), newStart.offsetInContainerNode(), exception); 869 range->setEnd(newStart.containerNode(), newStart.offsetInContainerNode(), exception); 870 return kit(range.get()); 871} 872 873- (DOMDocumentFragment *)_documentFragmentWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString 874{ 875 Frame* frame = _private->coreFrame; 876 if (!frame) 877 return nil; 878 879 Document* document = frame->document(); 880 if (!document) 881 return nil; 882 883 return kit(createFragmentFromMarkup(*document, markupString, baseURLString, DisallowScriptingContent).get()); 884} 885 886- (DOMDocumentFragment *)_documentFragmentWithNodesAsParagraphs:(NSArray *)nodes 887{ 888 Frame* frame = _private->coreFrame; 889 if (!frame) 890 return nil; 891 892 Document* document = frame->document(); 893 if (!document) 894 return nil; 895 896 NSEnumerator *nodeEnum = [nodes objectEnumerator]; 897 Vector<Node*> nodesVector; 898 DOMNode *node; 899 while ((node = [nodeEnum nextObject])) 900 nodesVector.append(core(node)); 901 902 RefPtr<DocumentFragment> fragment = document->createDocumentFragment(); 903 904 for (auto* node : nodesVector) { 905 RefPtr<Element> element = createDefaultParagraphElement(*document); 906 element->appendChild(node); 907 fragment->appendChild(element.release()); 908 } 909 910 return kit(fragment.release().get()); 911} 912 913- (void)_replaceSelectionWithNode:(DOMNode *)node selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle 914{ 915 DOMDocumentFragment *fragment = kit(_private->coreFrame->document()->createDocumentFragment().get()); 916 [fragment appendChild:node]; 917 [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:matchStyle]; 918} 919 920- (void)_insertParagraphSeparatorInQuotedContent 921{ 922 if (_private->coreFrame->selection().isNone()) 923 return; 924 925 _private->coreFrame->editor().insertParagraphSeparatorInQuotedContent(); 926} 927 928- (VisiblePosition)_visiblePositionForPoint:(NSPoint)point 929{ 930 // FIXME: Someone with access to Apple's sources could remove this needless wrapper call. 931 return _private->coreFrame->visiblePositionForPoint(IntPoint(point)); 932} 933 934- (DOMRange *)_characterRangeAtPoint:(NSPoint)point 935{ 936 return kit(_private->coreFrame->rangeForPoint(IntPoint(point)).get()); 937} 938 939- (DOMCSSStyleDeclaration *)_typingStyle 940{ 941 if (!_private->coreFrame) 942 return nil; 943 RefPtr<MutableStyleProperties> typingStyle = _private->coreFrame->selection().copyTypingStyle(); 944 if (!typingStyle) 945 return nil; 946 return kit(typingStyle->ensureCSSStyleDeclaration()); 947} 948 949- (void)_setTypingStyle:(DOMCSSStyleDeclaration *)style withUndoAction:(EditAction)undoAction 950{ 951 if (!_private->coreFrame || !style) 952 return; 953 // FIXME: We shouldn't have to create a copy here. 954 Ref<MutableStyleProperties> properties(core(style)->copyProperties()); 955 _private->coreFrame->editor().computeAndSetTypingStyle(&properties.get(), undoAction); 956} 957 958#if ENABLE(DRAG_SUPPORT) 959- (void)_dragSourceEndedAt:(NSPoint)windowLoc operation:(NSDragOperation)operation 960{ 961 if (!_private->coreFrame) 962 return; 963 FrameView* view = _private->coreFrame->view(); 964 if (!view) 965 return; 966 // FIXME: These are fake modifier keys here, but they should be real ones instead. 967 PlatformMouseEvent event(IntPoint(windowLoc), globalPoint(windowLoc, [view->platformWidget() window]), 968 LeftButton, PlatformEvent::MouseMoved, 0, false, false, false, false, currentTime()); 969 _private->coreFrame->eventHandler().dragSourceEndedAt(event, (DragOperation)operation); 970} 971#endif 972 973- (BOOL)_canProvideDocumentSource 974{ 975 Frame* frame = _private->coreFrame; 976 String mimeType = frame->document()->loader()->writer().mimeType(); 977 PluginData* pluginData = frame->page() ? &frame->page()->pluginData() : 0; 978 979 if (WebCore::DOMImplementation::isTextMIMEType(mimeType) 980 || Image::supportsType(mimeType) 981 || (pluginData && pluginData->supportsMimeType(mimeType, PluginData::AllPlugins) && frame->loader().subframeLoader().allowPlugins(NotAboutToInstantiatePlugin)) 982 || (pluginData && pluginData->supportsMimeType(mimeType, PluginData::OnlyApplicationPlugins))) 983 return NO; 984 985 return YES; 986} 987 988- (BOOL)_canSaveAsWebArchive 989{ 990 // Currently, all documents that we can view source for 991 // (HTML and XML documents) can also be saved as web archives 992 return [self _canProvideDocumentSource]; 993} 994 995- (void)_commitData:(NSData *)data 996{ 997 // FIXME: This really should be a setting. 998 Document* document = _private->coreFrame->document(); 999 document->setShouldCreateRenderers(_private->shouldCreateRenderers); 1000 1001 _private->coreFrame->loader().documentLoader()->commitData((const char *)[data bytes], [data length]); 1002} 1003 1004- (BOOL)_contentFilterDidHandleNavigationAction:(const WebCore::ResourceRequest &)request 1005{ 1006#if PLATFORM(IOS) 1007 if (ContentFilter *contentFilter = _private->contentFilterForBlockedLoad.get()) { 1008 RetainPtr<WebFrame> retainedMainFrame = [[self webView] mainFrame]; 1009 return contentFilter->handleUnblockRequestAndDispatchIfSuccessful(request, [retainedMainFrame] { 1010 WebThreadRun(^ { 1011 [retainedMainFrame reload]; 1012 }); 1013 }); 1014 } 1015#endif 1016 1017 return NO; 1018} 1019 1020@end 1021 1022@implementation WebFrame (WebPrivate) 1023 1024// FIXME: This exists only as a convenience for Safari, consider moving there. 1025- (BOOL)_isDescendantOfFrame:(WebFrame *)ancestor 1026{ 1027 Frame* coreFrame = _private->coreFrame; 1028 return coreFrame && coreFrame->tree().isDescendantOf(core(ancestor)); 1029} 1030 1031- (void)_setShouldCreateRenderers:(BOOL)shouldCreateRenderers 1032{ 1033 _private->shouldCreateRenderers = shouldCreateRenderers; 1034} 1035 1036#if !PLATFORM(IOS) 1037- (NSColor *)_bodyBackgroundColor 1038#else 1039- (CGColorRef)_bodyBackgroundColor 1040#endif 1041{ 1042 Document* document = _private->coreFrame->document(); 1043 if (!document) 1044 return nil; 1045 HTMLElement* body = document->body(); 1046 if (!body) 1047 return nil; 1048 RenderObject* bodyRenderer = body->renderer(); 1049 if (!bodyRenderer) 1050 return nil; 1051 Color color = bodyRenderer->style().visitedDependentColor(CSSPropertyBackgroundColor); 1052 if (!color.isValid()) 1053 return nil; 1054#if !PLATFORM(IOS) 1055 return nsColor(color); 1056#else 1057 return cachedCGColor(color, ColorSpaceDeviceRGB); 1058#endif 1059} 1060 1061- (BOOL)_isFrameSet 1062{ 1063 Document* document = _private->coreFrame->document(); 1064 return document && document->isFrameSet(); 1065} 1066 1067- (BOOL)_firstLayoutDone 1068{ 1069 return _private->coreFrame->loader().stateMachine().firstLayoutDone(); 1070} 1071 1072- (BOOL)_isVisuallyNonEmpty 1073{ 1074 if (FrameView* view = _private->coreFrame->view()) 1075 return view->isVisuallyNonEmpty(); 1076 return NO; 1077} 1078 1079static WebFrameLoadType toWebFrameLoadType(FrameLoadType frameLoadType) 1080{ 1081 switch (frameLoadType) { 1082 case FrameLoadType::Standard: 1083 return WebFrameLoadTypeStandard; 1084 case FrameLoadType::Back: 1085 return WebFrameLoadTypeBack; 1086 case FrameLoadType::Forward: 1087 return WebFrameLoadTypeForward; 1088 case FrameLoadType::IndexedBackForward: 1089 return WebFrameLoadTypeIndexedBackForward; 1090 case FrameLoadType::Reload: 1091 return WebFrameLoadTypeReload; 1092 case FrameLoadType::Same: 1093 return WebFrameLoadTypeSame; 1094 case FrameLoadType::RedirectWithLockedBackForwardList: 1095 return WebFrameLoadTypeInternal; 1096 case FrameLoadType::Replace: 1097 return WebFrameLoadTypeReplace; 1098 case FrameLoadType::ReloadFromOrigin: 1099 return WebFrameLoadTypeReloadFromOrigin; 1100 } 1101} 1102 1103- (WebFrameLoadType)_loadType 1104{ 1105 return toWebFrameLoadType(_private->coreFrame->loader().loadType()); 1106} 1107 1108#if PLATFORM(IOS) 1109- (BOOL)needsLayout 1110{ 1111 // Needed for Mail <rdar://problem/6228038> 1112 return _private->coreFrame ? [self _needsLayout] : NO; 1113} 1114 1115- (void)_setLoadsSynchronously:(BOOL)flag 1116{ 1117 _private->coreFrame->loader().setLoadsSynchronously(flag); 1118} 1119 1120- (BOOL)_loadsSynchronously 1121{ 1122 return _private->coreFrame->loader().loadsSynchronously(); 1123} 1124 1125// FIXME: selection 1126 1127- (NSArray *)_rectsForRange:(DOMRange *)domRange 1128{ 1129 Range *range = core(domRange); 1130 1131 1132 Vector<IntRect> intRects; 1133 range->textRects(intRects, NO); 1134 unsigned size = intRects.size(); 1135 1136 NSMutableArray *rectArray = [NSMutableArray arrayWithCapacity:size]; 1137 for (unsigned i = 0; i < size; i++) { 1138 [rectArray addObject:[NSValue valueWithRect:(CGRect )intRects[i]]]; 1139 } 1140 1141 return rectArray; 1142} 1143 1144- (DOMRange *)_selectionRangeForFirstPoint:(CGPoint)first secondPoint:(CGPoint)second 1145{ 1146 VisiblePosition firstPos = [self _visiblePositionForPoint:first]; 1147 VisiblePosition secondPos = [self _visiblePositionForPoint:second]; 1148 VisibleSelection selection(firstPos, secondPos); 1149 DOMRange *range = kit(selection.toNormalizedRange().get()); 1150 return range; 1151} 1152 1153- (DOMRange *)_selectionRangeForPoint:(CGPoint)point 1154{ 1155 VisiblePosition pos = [self _visiblePositionForPoint:point]; 1156 VisibleSelection selection(pos); 1157 DOMRange *range = kit(selection.toNormalizedRange().get()); 1158 return range; 1159} 1160 1161#endif // PLATFORM(IOS) 1162 1163- (NSRange)_selectedNSRange 1164{ 1165 return [self _convertToNSRange:_private->coreFrame->selection().toNormalizedRange().get()]; 1166} 1167 1168- (void)_selectNSRange:(NSRange)range 1169{ 1170 RefPtr<Range> domRange = [self _convertToDOMRange:range]; 1171 if (domRange) 1172 _private->coreFrame->selection().setSelection(VisibleSelection(domRange.get(), SEL_DEFAULT_AFFINITY)); 1173} 1174 1175- (BOOL)_isDisplayingStandaloneImage 1176{ 1177 Document* document = _private->coreFrame->document(); 1178 return document && document->isImageDocument(); 1179} 1180 1181- (unsigned)_pendingFrameUnloadEventCount 1182{ 1183 return _private->coreFrame->document()->domWindow()->pendingUnloadEventListeners(); 1184} 1185 1186#if ENABLE(NETSCAPE_PLUGIN_API) 1187- (void)_recursive_resumeNullEventsForAllNetscapePlugins 1188{ 1189 Frame* coreFrame = core(self); 1190 for (Frame* frame = coreFrame; frame; frame = frame->tree().traverseNext(coreFrame)) { 1191 NSView <WebDocumentView> *documentView = [[kit(frame) frameView] documentView]; 1192 if ([documentView isKindOfClass:[WebHTMLView class]]) 1193 [(WebHTMLView *)documentView _resumeNullEventsForAllNetscapePlugins]; 1194 } 1195} 1196 1197- (void)_recursive_pauseNullEventsForAllNetscapePlugins 1198{ 1199 Frame* coreFrame = core(self); 1200 for (Frame* frame = coreFrame; frame; frame = frame->tree().traverseNext(coreFrame)) { 1201 NSView <WebDocumentView> *documentView = [[kit(frame) frameView] documentView]; 1202 if ([documentView isKindOfClass:[WebHTMLView class]]) 1203 [(WebHTMLView *)documentView _pauseNullEventsForAllNetscapePlugins]; 1204 } 1205} 1206#endif 1207 1208#if PLATFORM(IOS) 1209- (unsigned)formElementsCharacterCount 1210{ 1211 WebCore::Frame *frame = core(self); 1212 return frame->formElementsCharacterCount(); 1213} 1214 1215- (void)setTimeoutsPaused:(BOOL)flag 1216{ 1217 id documentView = [_private->webFrameView documentView]; 1218 if ([documentView isKindOfClass:[WebHTMLView class]]) { 1219 if (Frame* coreFrame = _private->coreFrame) 1220 coreFrame->setTimersPaused(flag); 1221 } 1222} 1223 1224- (void)setPluginsPaused:(BOOL)flag 1225{ 1226 WebView *webView = getWebView(self); 1227 if (!webView) 1228 return; 1229 1230 if (flag) 1231 [webView _stopAllPlugIns]; 1232 else 1233 [webView _startAllPlugIns]; 1234} 1235 1236- (void)prepareForPause 1237{ 1238 id documentView = [_private->webFrameView documentView]; 1239 if ([documentView isKindOfClass:[WebHTMLView class]]) { 1240 if (Frame* coreFrame = _private->coreFrame) 1241 coreFrame->dispatchPageHideEventBeforePause(); 1242 } 1243} 1244 1245- (void)resumeFromPause 1246{ 1247 id documentView = [_private->webFrameView documentView]; 1248 if ([documentView isKindOfClass:[WebHTMLView class]]) { 1249 if (Frame* coreFrame = _private->coreFrame) 1250 coreFrame->dispatchPageShowEventBeforeResume(); 1251 } 1252} 1253 1254- (void)selectNSRange:(NSRange)range 1255{ 1256 [self _selectNSRange:range]; 1257} 1258 1259- (void)selectWithoutClosingTypingNSRange:(NSRange)range 1260{ 1261 RefPtr<Range> domRange = [self _convertToDOMRange:range]; 1262 if (domRange) { 1263 const VisibleSelection& newSelection = VisibleSelection(domRange.get(), SEL_DEFAULT_AFFINITY); 1264 _private->coreFrame->selection().setSelection(newSelection, 0); 1265 1266 _private->coreFrame->editor().ensureLastEditCommandHasCurrentSelectionIfOpenForMoreTyping(); 1267 } 1268} 1269 1270- (NSRange)selectedNSRange 1271{ 1272 return [self _selectedNSRange]; 1273} 1274 1275- (void)forceLayoutAdjustingViewSize:(BOOL)adjust 1276{ 1277 _private->coreFrame->view()->forceLayout(!adjust); 1278 if (adjust) 1279 _private->coreFrame->view()->adjustViewSize(); 1280} 1281 1282- (void)_handleKeyEvent:(WebEvent *)event 1283{ 1284 core(self)->eventHandler().keyEvent(event); 1285} 1286 1287- (void)_selectAll 1288{ 1289 core(self)->selection().selectAll(); 1290} 1291 1292- (void)_setSelectionFromNone 1293{ 1294 core(self)->selection().setSelectionFromNone(); 1295} 1296 1297- (void)_restoreViewState 1298{ 1299 ASSERT(!WebThreadIsEnabled() || WebThreadIsLocked()); 1300 _private->coreFrame->loader().client().restoreViewState(); 1301} 1302 1303- (void)_saveViewState 1304{ 1305 ASSERT(!WebThreadIsEnabled() || WebThreadIsLocked()); 1306 FrameLoader& frameLoader = _private->coreFrame->loader(); 1307 frameLoader.client().saveViewStateToItem(frameLoader.history().currentItem()); 1308} 1309 1310- (void)deviceOrientationChanged 1311{ 1312 WebThreadRun(^{ 1313 if (WebCore::Frame* frame = core(self)) 1314 frame->orientationChanged(); 1315 }); 1316} 1317 1318- (void)sendOrientationChangeEvent:(int)newOrientation 1319{ 1320 [self deviceOrientationChanged]; 1321} 1322 1323- (void)setNeedsLayout 1324{ 1325 WebCore::Frame *frame = core(self); 1326 if (frame->view()) 1327 frame->view()->setNeedsLayout(); 1328} 1329 1330- (CGSize)renderedSizeOfNode:(DOMNode *)node constrainedToWidth:(float)width 1331{ 1332 Node *n = core(node); 1333 RenderObject *r = n ? n->renderer() : 0; 1334 float w = std::min((float)r->maxPreferredLogicalWidth(), width); 1335 return r && r->isBox() ? CGSizeMake(w, toRenderBox(r)->height()) : CGSizeMake(0,0); 1336} 1337 1338- (DOMNode *)deepestNodeAtViewportLocation:(CGPoint)aViewportLocation 1339{ 1340 WebCore::Frame *frame = core(self); 1341 return kit(frame->deepestNodeAtLocation(FloatPoint(aViewportLocation))); 1342} 1343 1344- (DOMNode *)scrollableNodeAtViewportLocation:(CGPoint)aViewportLocation 1345{ 1346 WebCore::Frame *frame = core(self); 1347 WebCore::Node *node = frame->nodeRespondingToScrollWheelEvents(FloatPoint(aViewportLocation)); 1348 return kit(node); 1349} 1350 1351- (DOMNode *)approximateNodeAtViewportLocation:(CGPoint *)aViewportLocation 1352{ 1353 WebCore::Frame *frame = core(self); 1354 FloatPoint viewportLocation(*aViewportLocation); 1355 FloatPoint adjustedLocation; 1356 WebCore::Node *node = frame->nodeRespondingToClickEvents(viewportLocation, adjustedLocation); 1357 *aViewportLocation = adjustedLocation; 1358 return kit(node); 1359} 1360 1361- (CGRect)renderRectForPoint:(CGPoint)point isReplaced:(BOOL *)isReplaced fontSize:(float *)fontSize 1362{ 1363 WebCore::Frame *frame = core(self); 1364 bool replaced = false; 1365 CGRect rect = frame->renderRectForPoint(point, &replaced, fontSize); 1366 *isReplaced = replaced; 1367 return rect; 1368} 1369 1370- (void)_setProhibitsScrolling:(BOOL)flag 1371{ 1372 WebCore::Frame *frame = core(self); 1373 frame->view()->setProhibitsScrolling(flag); 1374} 1375 1376- (void)revealSelectionAtExtent:(BOOL)revealExtent 1377{ 1378 WebCore::Frame *frame = core(self); 1379 RevealExtentOption revealExtentOption = revealExtent ? RevealExtent : DoNotRevealExtent; 1380 frame->selection().revealSelection(ScrollAlignment::alignToEdgeIfNeeded, revealExtentOption); 1381} 1382 1383- (void)resetSelection 1384{ 1385 WebCore::Frame *frame = core(self); 1386 frame->selection().setSelection(frame->selection().selection()); 1387} 1388 1389- (BOOL)hasEditableSelection 1390{ 1391 WebCore::Frame *frame = core(self); 1392 return frame->selection().selection().isContentEditable(); 1393} 1394 1395- (int)preferredHeight 1396{ 1397 WebCore::Frame *frame = core(self); 1398 return frame->preferredHeight(); 1399} 1400 1401- (int)innerLineHeight:(DOMNode *)node 1402{ 1403 WebCore::Frame *frame = core(self); 1404 return frame->innerLineHeight(node); 1405} 1406 1407- (void)updateLayout 1408{ 1409 WebCore::Frame *frame = core(self); 1410 frame->updateLayout(); 1411} 1412 1413- (void)setIsActive:(BOOL)flag 1414{ 1415 WebCore::Frame *frame = core(self); 1416 frame->page()->focusController().setActive(flag); 1417} 1418 1419- (void)setSelectionChangeCallbacksDisabled:(BOOL)flag 1420{ 1421 WebCore::Frame *frame = core(self); 1422 frame->setSelectionChangeCallbacksDisabled(flag); 1423} 1424 1425- (NSRect)caretRect 1426{ 1427 WebCore::Frame *frame = core(self); 1428 return frame->caretRect(); 1429} 1430 1431- (NSRect)rectForScrollToVisible 1432{ 1433 WebCore::Frame *frame = core(self); 1434 return frame->rectForScrollToVisible(); 1435} 1436 1437- (void)setCaretColor:(CGColorRef)color 1438{ 1439 Color qColor = color ? Color(color) : Color::black; 1440 WebCore::Frame *frame = core(self); 1441 frame->selection().setCaretColor(qColor); 1442} 1443 1444- (NSView *)documentView 1445{ 1446 WebCore::Frame *frame = core(self); 1447 return [[kit(frame) frameView] documentView]; 1448} 1449 1450- (int)layoutCount 1451{ 1452 WebCore::Frame *frame = core(self); 1453 if (!frame || !frame->view()) 1454 return 0; 1455 return frame->view()->layoutCount(); 1456} 1457 1458- (BOOL)isTelephoneNumberParsingAllowed 1459{ 1460 Document *document = core(self)->document(); 1461 return document->isTelephoneNumberParsingAllowed(); 1462} 1463 1464- (BOOL)isTelephoneNumberParsingEnabled 1465{ 1466 Document *document = core(self)->document(); 1467 return document->isTelephoneNumberParsingEnabled(); 1468} 1469 1470- (BOOL)mediaDataLoadsAutomatically 1471{ 1472 WebCore::Frame *frame = core(self); 1473 if (WebCore::Page* page = frame->page()) 1474 return page->settings().mediaDataLoadsAutomatically(); 1475 1476 return NO; 1477} 1478 1479- (void)setMediaDataLoadsAutomatically:(BOOL)flag 1480{ 1481 WebCore::Frame *frame = core(self); 1482 if (WebCore::Page* page = frame->page()) 1483 page->settings().setMediaDataLoadsAutomatically(flag); 1484} 1485 1486- (DOMRange *)selectedDOMRange 1487{ 1488 WebCore::Frame *frame = core(self); 1489 RefPtr<WebCore::Range> range = frame->selection().toNormalizedRange(); 1490 return kit(range.get()); 1491} 1492 1493- (void)setSelectedDOMRange:(DOMRange *)range affinity:(NSSelectionAffinity)affinity closeTyping:(BOOL)closeTyping 1494{ 1495 WebCore::Frame *frame = core(self); 1496 1497 // Ensure the view becomes first responder. 1498 // This does not happen automatically on iOS because we don't forward 1499 // all the click events to WebKit. 1500 if (FrameView* frameView = frame->view()) { 1501 if (NSView *documentView = frameView->documentView()) { 1502 Page* page = frame->page(); 1503 if (!page) 1504 return; 1505 page->chrome().focusNSView(documentView); 1506 } 1507 } 1508 1509 frame->selection().setSelectedRange(core(range), (EAffinity)affinity, closeTyping); 1510 if (!closeTyping) 1511 frame->editor().ensureLastEditCommandHasCurrentSelectionIfOpenForMoreTyping(); 1512} 1513 1514- (NSSelectionAffinity)selectionAffinity 1515{ 1516 WebCore::Frame *frame = core(self); 1517 return (NSSelectionAffinity)(frame->selection().selection().affinity()); 1518} 1519 1520- (void)expandSelectionToElementContainingCaretSelection 1521{ 1522 WebCore::Frame *frame = core(self); 1523 frame->selection().expandSelectionToElementContainingCaretSelection(); 1524} 1525 1526- (DOMRange *)elementRangeContainingCaretSelection 1527{ 1528 WebCore::Frame *frame = core(self); 1529 RefPtr<WebCore::Range> range = frame->selection().elementRangeContainingCaretSelection(); 1530 return kit(range.get()); 1531} 1532 1533- (void)expandSelectionToWordContainingCaretSelection 1534{ 1535 WebCore::Frame *frame = core(self); 1536 frame->selection().expandSelectionToWordContainingCaretSelection(); 1537} 1538 1539- (void)expandSelectionToStartOfWordContainingCaretSelection 1540{ 1541 WebCore::Frame *frame = core(self); 1542 frame->selection().expandSelectionToStartOfWordContainingCaretSelection(); 1543} 1544 1545- (unichar)characterInRelationToCaretSelection:(int)amount 1546{ 1547 WebCore::Frame *frame = core(self); 1548 return frame->selection().characterInRelationToCaretSelection(amount); 1549} 1550 1551- (unichar)characterBeforeCaretSelection 1552{ 1553 WebCore::Frame *frame = core(self); 1554 return frame->selection().characterBeforeCaretSelection(); 1555} 1556 1557- (unichar)characterAfterCaretSelection 1558{ 1559 WebCore::Frame *frame = core(self); 1560 return frame->selection().characterAfterCaretSelection(); 1561} 1562 1563- (DOMRange *)wordRangeContainingCaretSelection 1564{ 1565 WebCore::Frame *frame = core(self); 1566 RefPtr<WebCore::Range> range = frame->selection().wordRangeContainingCaretSelection(); 1567 return kit(range.get()); 1568} 1569 1570- (NSString *)wordInRange:(DOMRange *)range 1571{ 1572 if (!range) 1573 return nil; 1574 return [self _stringForRange:range]; 1575} 1576 1577- (int)wordOffsetInRange:(DOMRange *)range 1578{ 1579 WebCore::Frame *frame = core(self); 1580 return frame->selection().wordOffsetInRange(core(range)); 1581} 1582 1583- (BOOL)spaceFollowsWordInRange:(DOMRange *)range 1584{ 1585 WebCore::Frame *frame = core(self); 1586 return frame->selection().spaceFollowsWordInRange(core(range)); 1587} 1588 1589- (NSArray *)wordsInCurrentParagraph 1590{ 1591 WebCore::Frame *frame = core(self); 1592 return frame->wordsInCurrentParagraph(); 1593} 1594 1595- (BOOL)selectionAtDocumentStart 1596{ 1597 WebCore::Frame *frame = core(self); 1598 1599 if (frame->selection().selection().isNone()) 1600 return NO; 1601 1602 frame->document()->updateLayout(); 1603 1604 return frame->selection().selectionAtDocumentStart(); 1605} 1606 1607- (BOOL)selectionAtSentenceStart 1608{ 1609 WebCore::Frame *frame = core(self); 1610 1611 if (frame->selection().selection().isNone()) 1612 return NO; 1613 1614 frame->document()->updateLayout(); 1615 1616 return frame->selection().selectionAtSentenceStart(); 1617} 1618 1619- (BOOL)selectionAtWordStart 1620{ 1621 WebCore::Frame *frame = core(self); 1622 1623 if (frame->selection().selection().isNone()) 1624 return NO; 1625 1626 frame->document()->updateLayout(); 1627 1628 return frame->selection().selectionAtWordStart(); 1629} 1630 1631- (DOMRange *)rangeByMovingCurrentSelection:(int)amount 1632{ 1633 WebCore::Frame *frame = core(self); 1634 RefPtr<WebCore::Range> range = frame->selection().rangeByMovingCurrentSelection(amount); 1635 return kit(range.get()); 1636} 1637 1638- (DOMRange *)rangeByExtendingCurrentSelection:(int)amount 1639{ 1640 WebCore::Frame *frame = core(self); 1641 RefPtr<WebCore::Range> range = frame->selection().rangeByExtendingCurrentSelection(amount); 1642 return kit(range.get()); 1643} 1644 1645- (void)selectNSRange:(NSRange)range onElement:(DOMElement *)element 1646{ 1647 WebCore::Frame *frame = core(self); 1648 1649 Document *doc = frame->document(); 1650 if (!doc) 1651 return; 1652 1653 Node *node = core(element); 1654 if (!node->inDocument()) 1655 return; 1656 1657 frame->selection().selectRangeOnElement(range.location, range.length, node); 1658} 1659 1660- (DOMRange *)markedTextDOMRange 1661{ 1662 WebCore::Frame *frame = core(self); 1663 if (!frame) 1664 return nil; 1665 1666 return kit(frame->editor().compositionRange().get()); 1667} 1668 1669- (void)setMarkedText:(NSString *)text selectedRange:(NSRange)newSelRange 1670{ 1671 WebCore::Frame *frame = core(self); 1672 if (!frame) 1673 return; 1674 1675 Vector<CompositionUnderline> underlines; 1676 frame->page()->chrome().client().suppressFormNotifications(); 1677 frame->editor().setComposition(text, underlines, newSelRange.location, NSMaxRange(newSelRange)); 1678 frame->page()->chrome().client().restoreFormNotifications(); 1679} 1680 1681- (void)setMarkedText:(NSString *)text forCandidates:(BOOL)forCandidates 1682{ 1683 WebCore::Frame *frame = core(self); 1684 if (!frame) 1685 return; 1686 1687 Vector<CompositionUnderline> underlines; 1688 frame->editor().setComposition(text, underlines, 0, [text length]); 1689} 1690 1691- (void)confirmMarkedText:(NSString *)text 1692{ 1693 WebCore::Frame *frame = core(self); 1694 if (!frame || !frame->editor().client()) 1695 return; 1696 1697 frame->page()->chrome().client().suppressFormNotifications(); 1698 if (text) 1699 frame->editor().confirmComposition(text); 1700 else 1701 frame->editor().confirmMarkedText(); 1702 frame->page()->chrome().client().restoreFormNotifications(); 1703} 1704 1705- (void)setText:(NSString *)text asChildOfElement:(DOMElement *)element 1706{ 1707 if (!element) 1708 return; 1709 1710 WebCore::Frame *frame = core(self); 1711 if (!frame || !frame->document()) 1712 return; 1713 1714 frame->editor().setTextAsChildOfElement(text, core(element)); 1715} 1716 1717- (void)setDictationPhrases:(NSArray *)dictationPhrases metadata:(id)metadata asChildOfElement:(DOMElement *)element 1718{ 1719 if (!element) 1720 return; 1721 1722 WebCore::Frame *frame = core(self); 1723 if (!frame) 1724 return; 1725 1726 frame->editor().setDictationPhrasesAsChildOfElement(vectorForDictationPhrasesArray(dictationPhrases), metadata, core(element)); 1727} 1728 1729- (NSArray *)interpretationsForCurrentRoot 1730{ 1731 return core(self)->interpretationsForCurrentRoot(); 1732} 1733 1734// Collects the ranges and metadata for all of the mars voltas in the root editable element. 1735- (void)getDictationResultRanges:(NSArray **)outRanges andMetadatas:(NSArray **)outMetadatas 1736{ 1737 ASSERT(outRanges); 1738 if (!outRanges) 1739 return; 1740 1741 // *outRanges should not already point to an array. 1742 ASSERT(!(*outRanges)); 1743 *outRanges = nil; 1744 1745 ASSERT(outMetadatas); 1746 if (!outMetadatas) 1747 return; 1748 1749 // *metadata should not already point to an array. 1750 ASSERT(!(*outMetadatas)); 1751 *outMetadatas = nil; 1752 1753 NSMutableArray *ranges = [NSMutableArray array]; 1754 NSMutableArray *metadatas = [NSMutableArray array]; 1755 1756 Frame *frame = core(self); 1757 Document *document = frame->document(); 1758 1759 const VisibleSelection& selection = frame->selection().selection(); 1760 Element *root = selection.selectionType() == VisibleSelection::NoSelection ? frame->document()->body() : selection.rootEditableElement(); 1761 1762 DOMRange *previousDOMRange = nil; 1763 id previousMetadata = nil; 1764 1765 for (Node* node = root; node; node = NodeTraversal::next(node)) { 1766 Vector<DocumentMarker*> markers = document->markers().markersFor(node); 1767 Vector<DocumentMarker*>::const_iterator end = markers.end(); 1768 for (Vector<DocumentMarker*>::const_iterator it = markers.begin(); it != end; ++it) { 1769 1770 if ((*it)->type() != DocumentMarker::DictationResult) 1771 continue; 1772 1773 const DocumentMarker* marker = *it; 1774 id metadata = marker->metadata(); 1775 1776 // All result markers should have metadata. 1777 ASSERT(metadata); 1778 if (!metadata) 1779 continue; 1780 1781 RefPtr<Range> range = Range::create(*document, node, marker->startOffset(), node, marker->endOffset()); 1782 DOMRange *domRange = kit(range.get()); 1783 1784 if (metadata != previousMetadata) { 1785 [metadatas addObject:metadata]; 1786 [ranges addObject:domRange]; 1787 previousMetadata = metadata; 1788 previousDOMRange = domRange; 1789 } else { 1790 // It is possible for a DocumentMarker to be split by editing. Adjacent markers with the 1791 // the same metadata are for the same result. So combine their ranges. 1792 ASSERT(previousDOMRange == [ranges lastObject]); 1793 [previousDOMRange retain]; 1794 [ranges removeLastObject]; 1795 DOMNode *startContainer = [domRange startContainer]; 1796 int startOffset = [domRange startOffset]; 1797 [previousDOMRange setEnd:startContainer offset:startOffset]; 1798 [ranges addObject:previousDOMRange]; 1799 [previousDOMRange release]; 1800 } 1801 } 1802 } 1803 1804 *outRanges = ranges; 1805 *outMetadatas = metadatas; 1806 1807 return; 1808} 1809 1810- (id)dictationResultMetadataForRange:(DOMRange *)range 1811{ 1812 if (!range) 1813 return nil; 1814 1815 Vector<DocumentMarker*> markers = core(self)->document()->markers().markersInRange(core(range), DocumentMarker::DictationResult); 1816 1817 // UIKit should only ever give us a DOMRange for a phrase with alternatives, which should not be part of more than one result. 1818 ASSERT(markers.size() <= 1); 1819 if (markers.size() == 0) 1820 return nil; 1821 1822 return markers[0]->metadata(); 1823} 1824 1825- (void)recursiveSetUpdateAppearanceEnabled:(BOOL)enabled 1826{ 1827 WebCore::Frame *frame = core(self); 1828 if (frame) 1829 frame->recursiveSetUpdateAppearanceEnabled(enabled); 1830} 1831 1832// WebCoreFrameBridge methods used by iOS applications and frameworks 1833// FIXME: WebCoreFrameBridge is long gone. Can we remove these methods? 1834 1835+ (NSString *)stringWithData:(NSData *)data textEncodingName:(NSString *)textEncodingName 1836{ 1837 WebCore::TextEncoding encoding(textEncodingName); 1838 if (!encoding.isValid()) 1839 encoding = WindowsLatin1Encoding(); 1840 return encoding.decode(reinterpret_cast<const char*>([data bytes]), [data length]); 1841} 1842 1843- (NSRect)caretRectAtNode:(DOMNode *)node offset:(int)offset affinity:(NSSelectionAffinity)affinity 1844{ 1845 return [self _caretRectAtPosition:createLegacyEditingPosition(core(node), offset) affinity:affinity]; 1846} 1847 1848- (DOMRange *)characterRangeAtPoint:(NSPoint)point 1849{ 1850 return [self _characterRangeAtPoint:point]; 1851} 1852 1853- (NSRange)convertDOMRangeToNSRange:(DOMRange *)range 1854{ 1855 return [self _convertDOMRangeToNSRange:range]; 1856} 1857 1858- (DOMRange *)convertNSRangeToDOMRange:(NSRange)nsrange 1859{ 1860 return [self _convertNSRangeToDOMRange:nsrange]; 1861} 1862 1863- (NSRect)firstRectForDOMRange:(DOMRange *)range 1864{ 1865 return [self _firstRectForDOMRange:range]; 1866} 1867 1868- (CTFontRef)fontForSelection:(BOOL *)hasMultipleFonts 1869{ 1870 bool multipleFonts = false; 1871 CTFontRef font = nil; 1872 if (_private->coreFrame) { 1873 const SimpleFontData* fd = _private->coreFrame->editor().fontForSelection(multipleFonts); 1874 if (fd) 1875 font = fd->getCTFont(); 1876 } 1877 1878 if (hasMultipleFonts) 1879 *hasMultipleFonts = multipleFonts; 1880 return font; 1881} 1882 1883- (void)sendScrollEvent 1884{ 1885 ASSERT(WebThreadIsLockedOrDisabled()); 1886 _private->coreFrame->eventHandler().sendScrollEvent(); 1887} 1888 1889- (void)_userScrolled 1890{ 1891 ASSERT(WebThreadIsLockedOrDisabled()); 1892 if (FrameView* view = _private->coreFrame->view()) 1893 view->setWasScrolledByUser(true); 1894} 1895 1896- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)string forceUserGesture:(BOOL)forceUserGesture 1897{ 1898 return [self _stringByEvaluatingJavaScriptFromString:string forceUserGesture:forceUserGesture]; 1899} 1900 1901- (NSString *)stringForRange:(DOMRange *)range 1902{ 1903 return [self _stringForRange:range]; 1904} 1905 1906// 1907// FIXME: We needed to add this method for iOS due to the opensource version's inclusion of 1908// matchStyle:YES. It seems odd that we should need to explicitly match style, given that the 1909// fragment is being made out of plain text, which shouldn't be carrying any style of its own. 1910// When we paste that it will pick up its style from the surrounding content. What else would 1911// we expect? If we flipped that matchStyle bit to NO, we could probably just get rid 1912// of this method, and call the standard WebKit version. 1913// 1914// There's a second problem here, too, which is that ReplaceSelectionCommand sometimes adds 1915// redundant style. 1916// 1917- (void)_replaceSelectionWithText:(NSString *)text selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle 1918{ 1919 RefPtr<Range> range = _private->coreFrame->selection().toNormalizedRange(); 1920 1921 DOMDocumentFragment* fragment = range ? kit(createFragmentFromText(*range, text).get()) : nil; 1922 [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:matchStyle]; 1923} 1924 1925- (void)_replaceSelectionWithWebArchive:(WebArchive *)webArchive selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace 1926{ 1927 NSArray* subresources = [webArchive subresources]; 1928 for (WebResource* subresource in subresources) { 1929 if (![[self dataSource] subresourceForURL:[subresource URL]]) 1930 [[self dataSource] addSubresource:subresource]; 1931 } 1932 1933 DOMDocumentFragment* fragment = [[self dataSource] _documentFragmentWithArchive:webArchive]; 1934 [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:NO]; 1935} 1936 1937#endif // PLATFORM(IOS) 1938 1939#if ENABLE(IOS_TEXT_AUTOSIZING) 1940- (void)resetTextAutosizingBeforeLayout 1941{ 1942 id documentView = [_private->webFrameView documentView]; 1943 if (![documentView isKindOfClass:[WebHTMLView class]]) 1944 return; 1945 1946 Frame* coreFrame = core(self); 1947 for (Frame* frame = coreFrame; frame; frame = frame->tree().traverseNext(coreFrame)) { 1948 Document *doc = frame->document(); 1949 if (!doc || !doc->renderView()) 1950 continue; 1951 doc->renderView()->resetTextAutosizing(); 1952 } 1953} 1954 1955- (void)_setVisibleSize:(CGSize)size 1956{ 1957 [self _setTextAutosizingWidth:size.width]; 1958} 1959 1960- (void)_setTextAutosizingWidth:(CGFloat)width 1961{ 1962 WebCore::Frame* frame = core(self); 1963 Page* page = frame->page(); 1964 if (!page) 1965 return; 1966 1967 page->setTextAutosizingWidth(width); 1968} 1969#else 1970- (void)resetTextAutosizingBeforeLayout 1971{ 1972} 1973 1974- (void)_setVisibleSize:(CGSize)size 1975{ 1976} 1977 1978- (void)_setTextAutosizingWidth:(CGFloat)width 1979{ 1980} 1981#endif // ENABLE(IOS_TEXT_AUTOSIZING) 1982 1983- (void)_replaceSelectionWithFragment:(DOMDocumentFragment *)fragment selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle 1984{ 1985 if (_private->coreFrame->selection().isNone() || !fragment) 1986 return; 1987 _private->coreFrame->editor().replaceSelectionWithFragment(core(fragment), selectReplacement, smartReplace, matchStyle); 1988} 1989 1990#if PLATFORM(IOS) 1991- (void)removeUnchangeableStyles 1992{ 1993 _private->coreFrame->editor().removeUnchangeableStyles(); 1994} 1995 1996- (BOOL)hasRichlyEditableSelection 1997{ 1998 return _private->coreFrame->selection().selection().isContentRichlyEditable(); 1999} 2000#endif 2001 2002- (void)_replaceSelectionWithText:(NSString *)text selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace 2003{ 2004 RefPtr<Range> range = _private->coreFrame->selection().toNormalizedRange(); 2005 2006 DOMDocumentFragment* fragment = range ? kit(createFragmentFromText(*range, text).get()) : nil; 2007 [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:YES]; 2008} 2009 2010- (void)_replaceSelectionWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace 2011{ 2012 DOMDocumentFragment *fragment = [self _documentFragmentWithMarkupString:markupString baseURLString:baseURLString]; 2013 [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:NO]; 2014} 2015 2016#if !PLATFORM(IOS) 2017// Determines whether whitespace needs to be added around aString to preserve proper spacing and 2018// punctuation when it's inserted into the receiver's text over charRange. Returns by reference 2019// in beforeString and afterString any whitespace that should be added, unless either or both are 2020// nil. Both are returned as nil if aString is nil or if smart insertion and deletion are disabled. 2021- (void)_smartInsertForString:(NSString *)pasteString replacingRange:(DOMRange *)rangeToReplace beforeString:(NSString **)beforeString afterString:(NSString **)afterString 2022{ 2023 // give back nil pointers in case of early returns 2024 if (beforeString) 2025 *beforeString = nil; 2026 if (afterString) 2027 *afterString = nil; 2028 2029 // inspect destination 2030 Node *startContainer = core([rangeToReplace startContainer]); 2031 Node *endContainer = core([rangeToReplace endContainer]); 2032 2033 Position startPos(startContainer, [rangeToReplace startOffset], Position::PositionIsOffsetInAnchor); 2034 Position endPos(endContainer, [rangeToReplace endOffset], Position::PositionIsOffsetInAnchor); 2035 2036 VisiblePosition startVisiblePos = VisiblePosition(startPos, VP_DEFAULT_AFFINITY); 2037 VisiblePosition endVisiblePos = VisiblePosition(endPos, VP_DEFAULT_AFFINITY); 2038 2039 // this check also ensures startContainer, startPos, endContainer, and endPos are non-null 2040 if (startVisiblePos.isNull() || endVisiblePos.isNull()) 2041 return; 2042 2043 bool addLeadingSpace = startPos.leadingWhitespacePosition(VP_DEFAULT_AFFINITY, true).isNull() && !isStartOfParagraph(startVisiblePos); 2044 if (addLeadingSpace) 2045 if (UChar previousChar = startVisiblePos.previous().characterAfter()) 2046 addLeadingSpace = !isCharacterSmartReplaceExempt(previousChar, true); 2047 2048 bool addTrailingSpace = endPos.trailingWhitespacePosition(VP_DEFAULT_AFFINITY, true).isNull() && !isEndOfParagraph(endVisiblePos); 2049 if (addTrailingSpace) 2050 if (UChar thisChar = endVisiblePos.characterAfter()) 2051 addTrailingSpace = !isCharacterSmartReplaceExempt(thisChar, false); 2052 2053 // inspect source 2054 bool hasWhitespaceAtStart = false; 2055 bool hasWhitespaceAtEnd = false; 2056 unsigned pasteLength = [pasteString length]; 2057 if (pasteLength > 0) { 2058 NSCharacterSet *whiteSet = [NSCharacterSet whitespaceAndNewlineCharacterSet]; 2059 2060 if ([whiteSet characterIsMember:[pasteString characterAtIndex:0]]) { 2061 hasWhitespaceAtStart = YES; 2062 } 2063 if ([whiteSet characterIsMember:[pasteString characterAtIndex:(pasteLength - 1)]]) { 2064 hasWhitespaceAtEnd = YES; 2065 } 2066 } 2067 2068 // issue the verdict 2069 if (beforeString && addLeadingSpace && !hasWhitespaceAtStart) 2070 *beforeString = @" "; 2071 if (afterString && addTrailingSpace && !hasWhitespaceAtEnd) 2072 *afterString = @" "; 2073} 2074#endif // !PLATFORM(IOS) 2075 2076- (NSMutableDictionary *)_cacheabilityDictionary 2077{ 2078 NSMutableDictionary *result = [NSMutableDictionary dictionary]; 2079 2080 FrameLoader& frameLoader = _private->coreFrame->loader(); 2081 DocumentLoader* documentLoader = frameLoader.documentLoader(); 2082 if (documentLoader && !documentLoader->mainDocumentError().isNull()) 2083 [result setObject:(NSError *)documentLoader->mainDocumentError() forKey:WebFrameMainDocumentError]; 2084 2085 if (frameLoader.subframeLoader().containsPlugins()) 2086 [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameHasPlugins]; 2087 2088 if (DOMWindow* domWindow = _private->coreFrame->document()->domWindow()) { 2089 if (domWindow->hasEventListeners(eventNames().unloadEvent)) 2090 [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameHasUnloadListener]; 2091 if (domWindow->optionalApplicationCache()) 2092 [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameUsesApplicationCache]; 2093 } 2094 2095 if (Document* document = _private->coreFrame->document()) { 2096#if ENABLE(SQL_DATABASE) 2097 if (DatabaseManager::manager().hasOpenDatabases(document)) 2098 [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameUsesDatabases]; 2099#endif 2100 if (!document->canSuspendActiveDOMObjects()) 2101 [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameCanSuspendActiveDOMObjects]; 2102 } 2103 2104 return result; 2105} 2106 2107- (BOOL)_allowsFollowingLink:(NSURL *)URL 2108{ 2109 if (!_private->coreFrame) 2110 return YES; 2111 return _private->coreFrame->document()->securityOrigin()->canDisplay(URL); 2112} 2113 2114- (NSString *)_stringByEvaluatingJavaScriptFromString:(NSString *)string withGlobalObject:(JSObjectRef)globalObjectRef inScriptWorld:(WebScriptWorld *)world 2115{ 2116 if (!string) 2117 return @""; 2118 2119 if (!world) 2120 return @""; 2121 2122 // Start off with some guess at a frame and a global object, we'll try to do better...! 2123 JSDOMWindow* anyWorldGlobalObject = _private->coreFrame->script().globalObject(mainThreadNormalWorld()); 2124 2125 // The global object is probably a shell object? - if so, we know how to use this! 2126 JSC::JSObject* globalObjectObj = toJS(globalObjectRef); 2127 if (!strcmp(globalObjectObj->classInfo()->className, "JSDOMWindowShell")) 2128 anyWorldGlobalObject = static_cast<JSDOMWindowShell*>(globalObjectObj)->window(); 2129 2130 // Get the frame frome the global object we've settled on. 2131 Frame* frame = anyWorldGlobalObject->impl().frame(); 2132 ASSERT(frame->document()); 2133 RetainPtr<WebFrame> webFrame(kit(frame)); // Running arbitrary JavaScript can destroy the frame. 2134 2135 JSC::JSValue result = frame->script().executeScriptInWorld(*core(world), string, true).jsValue(); 2136 2137 if (!webFrame->_private->coreFrame) // In case the script removed our frame from the page. 2138 return @""; 2139 2140 // This bizarre set of rules matches behavior from WebKit for Safari 2.0. 2141 // If you don't like it, use -[WebScriptObject evaluateWebScript:] or 2142 // JSEvaluateScript instead, since they have less surprising semantics. 2143 if (!result || (!result.isBoolean() && !result.isString() && !result.isNumber())) 2144 return @""; 2145 2146 JSC::ExecState* exec = anyWorldGlobalObject->globalExec(); 2147 JSC::JSLockHolder lock(exec); 2148 return result.toWTFString(exec); 2149} 2150 2151- (JSGlobalContextRef)_globalContextForScriptWorld:(WebScriptWorld *)world 2152{ 2153 Frame* coreFrame = _private->coreFrame; 2154 if (!coreFrame) 2155 return 0; 2156 DOMWrapperWorld* coreWorld = core(world); 2157 if (!coreWorld) 2158 return 0; 2159 return toGlobalRef(coreFrame->script().globalObject(*coreWorld)->globalExec()); 2160} 2161 2162#if JSC_OBJC_API_ENABLED 2163- (JSContext *)_javaScriptContextForScriptWorld:(WebScriptWorld *)world 2164{ 2165 JSGlobalContextRef globalContextRef = [self _globalContextForScriptWorld:world]; 2166 if (!globalContextRef) 2167 return 0; 2168 return [JSContext contextWithJSGlobalContextRef:globalContextRef]; 2169} 2170#endif 2171 2172#if !PLATFORM(IOS) 2173- (void)setAllowsScrollersToOverlapContent:(BOOL)flag 2174{ 2175 ASSERT([[[self frameView] _scrollView] isKindOfClass:[WebDynamicScrollBarsView class]]); 2176 [(WebDynamicScrollBarsView *)[[self frameView] _scrollView] setAllowsScrollersToOverlapContent:flag]; 2177} 2178 2179- (void)setAlwaysHideHorizontalScroller:(BOOL)flag 2180{ 2181 ASSERT([[[self frameView] _scrollView] isKindOfClass:[WebDynamicScrollBarsView class]]); 2182 [(WebDynamicScrollBarsView *)[[self frameView] _scrollView] setAlwaysHideHorizontalScroller:flag]; 2183} 2184- (void)setAlwaysHideVerticalScroller:(BOOL)flag 2185{ 2186 ASSERT([[[self frameView] _scrollView] isKindOfClass:[WebDynamicScrollBarsView class]]); 2187 [(WebDynamicScrollBarsView *)[[self frameView] _scrollView] setAlwaysHideVerticalScroller:flag]; 2188} 2189#endif 2190 2191- (void)setAccessibleName:(NSString *)name 2192{ 2193#if HAVE(ACCESSIBILITY) 2194 if (!AXObjectCache::accessibilityEnabled()) 2195 return; 2196 2197 if (!_private->coreFrame || !_private->coreFrame->document()) 2198 return; 2199 2200 AccessibilityObject* rootObject = _private->coreFrame->document()->axObjectCache()->rootObject(); 2201 if (rootObject) { 2202 String strName(name); 2203 rootObject->setAccessibleName(strName); 2204 } 2205#endif 2206} 2207 2208- (BOOL)enhancedAccessibilityEnabled 2209{ 2210#if HAVE(ACCESSIBILITY) 2211 return AXObjectCache::accessibilityEnhancedUserInterfaceEnabled(); 2212#else 2213 return NO; 2214#endif 2215} 2216 2217- (void)setEnhancedAccessibility:(BOOL)enable 2218{ 2219#if HAVE(ACCESSIBILITY) 2220 AXObjectCache::setEnhancedUserInterfaceAccessibility(enable); 2221#endif 2222} 2223 2224- (NSString*)_layerTreeAsText 2225{ 2226 Frame* coreFrame = _private->coreFrame; 2227 if (!coreFrame) 2228 return @""; 2229 2230 return coreFrame->layerTreeAsText(); 2231} 2232 2233- (id)accessibilityRoot 2234{ 2235#if HAVE(ACCESSIBILITY) 2236 if (!AXObjectCache::accessibilityEnabled()) { 2237 AXObjectCache::enableAccessibility(); 2238#if !PLATFORM(IOS) 2239 AXObjectCache::setEnhancedUserInterfaceAccessibility([[NSApp accessibilityAttributeValue:NSAccessibilityEnhancedUserInterfaceAttribute] boolValue]); 2240#endif 2241 } 2242 2243 if (!_private->coreFrame) 2244 return nil; 2245 2246 Document* document = _private->coreFrame->document(); 2247 if (!document || !document->axObjectCache()) 2248 return nil; 2249 2250 AccessibilityObject* rootObject = document->axObjectCache()->rootObjectForFrame(_private->coreFrame); 2251 if (!rootObject) 2252 return nil; 2253 2254 // The root object will be a WebCore scroll view object. In WK1, scroll views are handled 2255 // by the system and the root object should be the web area (instead of the scroll view). 2256 if (rootObject->isAttachment() && rootObject->firstChild()) 2257 return rootObject->firstChild()->wrapper(); 2258 2259 return rootObject->wrapper(); 2260#else 2261 return nil; 2262#endif 2263} 2264 2265- (void)_clearOpener 2266{ 2267 Frame* coreFrame = _private->coreFrame; 2268 if (coreFrame) 2269 coreFrame->loader().setOpener(0); 2270} 2271 2272// Used by pagination code called from AppKit when a standalone web page is printed. 2273- (NSArray *)_computePageRectsWithPrintScaleFactor:(float)printScaleFactor pageSize:(NSSize)pageSize 2274{ 2275 if (printScaleFactor <= 0) { 2276 LOG_ERROR("printScaleFactor has bad value %.2f", printScaleFactor); 2277 return [NSArray array]; 2278 } 2279 2280 if (!_private->coreFrame) 2281 return [NSArray array]; 2282 if (!_private->coreFrame->document()) 2283 return [NSArray array]; 2284 if (!_private->coreFrame->view()) 2285 return [NSArray array]; 2286 if (!_private->coreFrame->view()->documentView()) 2287 return [NSArray array]; 2288 2289 RenderView* root = _private->coreFrame->document()->renderView(); 2290 if (!root) 2291 return [NSArray array]; 2292 2293 const LayoutRect& documentRect = root->documentRect(); 2294 float printWidth = root->style().isHorizontalWritingMode() ? static_cast<float>(documentRect.width()) / printScaleFactor : pageSize.width; 2295 float printHeight = root->style().isHorizontalWritingMode() ? pageSize.height : static_cast<float>(documentRect.height()) / printScaleFactor; 2296 2297 PrintContext printContext(_private->coreFrame); 2298 printContext.computePageRectsWithPageSize(FloatSize(printWidth, printHeight), true); 2299 const Vector<IntRect>& pageRects = printContext.pageRects(); 2300 2301 size_t size = pageRects.size(); 2302 NSMutableArray *pages = [NSMutableArray arrayWithCapacity:size]; 2303 for (size_t i = 0; i < size; ++i) 2304 [pages addObject:[NSValue valueWithRect:NSRect(pageRects[i])]]; 2305 return pages; 2306} 2307 2308#if PLATFORM(IOS) 2309- (DOMDocumentFragment *)_documentFragmentForText:(NSString *)text 2310{ 2311 return kit(createFragmentFromText(*_private->coreFrame->selection().toNormalizedRange().get(), text).get()); 2312} 2313 2314- (DOMDocumentFragment *)_documentFragmentForWebArchive:(WebArchive *)webArchive 2315{ 2316 return [[self dataSource] _documentFragmentWithArchive:webArchive]; 2317} 2318 2319- (DOMDocumentFragment *)_documentFragmentForImageData:(NSData *)data withRelativeURLPart:(NSString *)relativeURLPart andMIMEType:(NSString *)mimeType 2320{ 2321 WebResource *resource = [[WebResource alloc] initWithData:data 2322 URL:[NSURL uniqueURLWithRelativePart:relativeURLPart] 2323 MIMEType:mimeType 2324 textEncodingName:nil 2325 frameName:nil]; 2326 DOMDocumentFragment *fragment = [[self _dataSource] _documentFragmentWithImageResource:resource]; 2327 [resource release]; 2328 return fragment; 2329} 2330 2331- (BOOL)focusedNodeHasContent 2332{ 2333 Frame* coreFrame = _private->coreFrame; 2334 2335 Element* root; 2336 const VisibleSelection& selection = coreFrame->selection().selection(); 2337 if (selection.isNone() || !selection.isContentEditable()) 2338 root = coreFrame->document()->body(); 2339 else { 2340 // Can't use the focusedNode here because we want the root of the shadow tree for form elements. 2341 root = selection.rootEditableElement(); 2342 } 2343 // Early return to avoid the expense of creating VisiblePositions. 2344 // FIXME: We fail to compute a root for SVG, we have a null check here so that we don't crash. 2345 if (!root || !root->hasChildNodes()) 2346 return NO; 2347 2348 VisiblePosition first(createLegacyEditingPosition(root, 0)); 2349 VisiblePosition last(createLegacyEditingPosition(root, root->childNodeCount())); 2350 return first != last; 2351} 2352 2353- (void)_dispatchDidReceiveTitle:(NSString *)title 2354{ 2355 Frame* coreFrame = _private->coreFrame; 2356 if (!coreFrame) 2357 return; 2358 coreFrame->loader().client().dispatchDidReceiveTitle(StringWithDirection(title, LTR)); 2359} 2360#endif // PLATFORM(IOS) 2361 2362- (JSValueRef)jsWrapperForNode:(DOMNode *)node inScriptWorld:(WebScriptWorld *)world 2363{ 2364 Frame* coreFrame = _private->coreFrame; 2365 if (!coreFrame) 2366 return 0; 2367 2368 if (!world) 2369 return 0; 2370 2371 JSDOMWindow* globalObject = coreFrame->script().globalObject(*core(world)); 2372 JSC::ExecState* exec = globalObject->globalExec(); 2373 2374 JSC::JSLockHolder lock(exec); 2375 return toRef(exec, toJS(exec, globalObject, core(node))); 2376} 2377 2378- (NSDictionary *)elementAtPoint:(NSPoint)point 2379{ 2380 Frame* coreFrame = _private->coreFrame; 2381 if (!coreFrame) 2382 return nil; 2383 return [[[WebElementDictionary alloc] initWithHitTestResult:coreFrame->eventHandler().hitTestResultAtPoint(IntPoint(point), HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::IgnoreClipping | HitTestRequest::DisallowShadowContent)] autorelease]; 2384} 2385 2386- (NSURL *)_unreachableURL 2387{ 2388 return [[self _dataSource] unreachableURL]; 2389} 2390 2391@end 2392 2393@implementation WebFrame 2394 2395- (instancetype)init 2396{ 2397 return nil; 2398} 2399 2400// Should be deprecated. 2401- (instancetype)initWithName:(NSString *)name webFrameView:(WebFrameView *)view webView:(WebView *)webView 2402{ 2403 return nil; 2404} 2405 2406- (void)dealloc 2407{ 2408 if (_private && _private->includedInWebKitStatistics) 2409 --WebFrameCount; 2410 2411 [_private release]; 2412 2413 [super dealloc]; 2414} 2415 2416- (void)finalize 2417{ 2418 if (_private && _private->includedInWebKitStatistics) 2419 --WebFrameCount; 2420 2421 [super finalize]; 2422} 2423 2424- (NSString *)name 2425{ 2426 Frame* coreFrame = _private->coreFrame; 2427 if (!coreFrame) 2428 return nil; 2429 return coreFrame->tree().uniqueName(); 2430} 2431 2432- (WebFrameView *)frameView 2433{ 2434 return _private->webFrameView; 2435} 2436 2437- (WebView *)webView 2438{ 2439 return getWebView(self); 2440} 2441 2442static bool needsMicrosoftMessengerDOMDocumentWorkaround() 2443{ 2444 static bool needsWorkaround = applicationIsMicrosoftMessenger() && [[[NSBundle mainBundle] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey] compare:@"7.1" options:NSNumericSearch] == NSOrderedAscending; 2445 return needsWorkaround; 2446} 2447 2448- (DOMDocument *)DOMDocument 2449{ 2450 if (needsMicrosoftMessengerDOMDocumentWorkaround() && !pthread_main_np()) 2451 return nil; 2452 2453 Frame* coreFrame = _private->coreFrame; 2454 if (!coreFrame) 2455 return nil; 2456 2457 // FIXME: <rdar://problem/5145841> When loading a custom view/representation 2458 // into a web frame, the old document can still be around. This makes sure that 2459 // we'll return nil in those cases. 2460 if (![[self _dataSource] _isDocumentHTML]) 2461 return nil; 2462 2463 Document* document = coreFrame->document(); 2464 2465 // According to the documentation, we should return nil if the frame doesn't have a document. 2466 // While full-frame images and plugins do have an underlying HTML document, we return nil here to be 2467 // backwards compatible. 2468 if (document && (document->isPluginDocument() || document->isImageDocument())) 2469 return nil; 2470 2471 return kit(coreFrame->document()); 2472} 2473 2474- (DOMHTMLElement *)frameElement 2475{ 2476 Frame* coreFrame = _private->coreFrame; 2477 if (!coreFrame) 2478 return nil; 2479 return kit(coreFrame->ownerElement()); 2480} 2481 2482- (WebDataSource *)provisionalDataSource 2483{ 2484 Frame* coreFrame = _private->coreFrame; 2485 return coreFrame ? dataSource(coreFrame->loader().provisionalDocumentLoader()) : nil; 2486} 2487 2488- (WebDataSource *)dataSource 2489{ 2490 Frame* coreFrame = _private->coreFrame; 2491 return coreFrame && coreFrame->loader().frameHasLoaded() ? [self _dataSource] : nil; 2492} 2493 2494- (void)loadRequest:(NSURLRequest *)request 2495{ 2496 Frame* coreFrame = _private->coreFrame; 2497 if (!coreFrame) 2498 return; 2499 2500 ResourceRequest resourceRequest(request); 2501 2502 // Some users of WebKit API incorrectly use "file path as URL" style requests which are invalid. 2503 // By re-writing those URLs here we technically break the -[WebDataSource initialRequest] API 2504 // but that is necessary to implement this quirk only at the API boundary. 2505 // Note that other users of WebKit API use nil requests or requests with nil URLs or empty URLs, so we 2506 // only implement this workaround when the request had a non-nil or non-empty URL. 2507 if (!resourceRequest.url().isValid() && !resourceRequest.url().isEmpty()) 2508 resourceRequest.setURL([NSURL URLWithString:[@"file:" stringByAppendingString:[[request URL] absoluteString]]]); 2509 2510 coreFrame->loader().load(FrameLoadRequest(coreFrame, resourceRequest)); 2511} 2512 2513static NSURL *createUniqueWebDataURL() 2514{ 2515 CFUUIDRef UUIDRef = CFUUIDCreate(kCFAllocatorDefault); 2516 NSString *UUIDString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, UUIDRef); 2517 CFRelease(UUIDRef); 2518 NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:@"applewebdata://%@", UUIDString]]; 2519 CFRelease(UUIDString); 2520 return URL; 2521} 2522 2523- (void)_loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)baseURL unreachableURL:(NSURL *)unreachableURL 2524{ 2525#if !PLATFORM(IOS) 2526 if (!pthread_main_np()) 2527 return [[self _webkit_invokeOnMainThread] _loadData:data MIMEType:MIMEType textEncodingName:encodingName baseURL:baseURL unreachableURL:unreachableURL]; 2528#endif 2529 2530 URL responseURL; 2531 if (!baseURL) { 2532 baseURL = blankURL(); 2533 responseURL = createUniqueWebDataURL(); 2534 } 2535 2536#if USE(QUICK_LOOK) 2537 if (shouldUseQuickLookForMIMEType(MIMEType)) { 2538 URL qlURL = responseURL; 2539 if (qlURL.isEmpty()) 2540 qlURL = [baseURL absoluteURL]; 2541 OwnPtr<ResourceRequest> qlRequest(registerQLPreviewConverterIfNeeded((NSURL *)qlURL, MIMEType, data)); 2542 if (qlRequest) { 2543 _private->coreFrame->loader().load(FrameLoadRequest(_private->coreFrame, *qlRequest)); 2544 return; 2545 } 2546 } 2547#endif // USE(QUICK_LOOK) 2548 2549 ResourceRequest request([baseURL absoluteURL]); 2550 2551#if !PLATFORM(IOS) 2552 // hack because Mail checks for this property to detect data / archive loads 2553 [NSURLProtocol setProperty:@"" forKey:@"WebDataRequest" inRequest:(NSMutableURLRequest *)request.nsURLRequest(UpdateHTTPBody)]; 2554#endif 2555 2556 SubstituteData substituteData(WebCore::SharedBuffer::wrapNSData(data), MIMEType, encodingName, [unreachableURL absoluteURL], responseURL); 2557 2558 _private->coreFrame->loader().load(FrameLoadRequest(_private->coreFrame, request, substituteData)); 2559} 2560 2561 2562- (void)loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)baseURL 2563{ 2564 WebCoreThreadViolationCheckRoundTwo(); 2565 2566 if (!MIMEType) 2567 MIMEType = @"text/html"; 2568 [self _loadData:data MIMEType:MIMEType textEncodingName:encodingName baseURL:[baseURL _webkit_URLFromURLOrSchemelessFileURL] unreachableURL:nil]; 2569} 2570 2571- (void)_loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL unreachableURL:(NSURL *)unreachableURL 2572{ 2573 NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding]; 2574 [self _loadData:data MIMEType:@"text/html" textEncodingName:@"UTF-8" baseURL:baseURL unreachableURL:unreachableURL]; 2575} 2576 2577- (void)loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL 2578{ 2579 WebCoreThreadViolationCheckRoundTwo(); 2580 2581 [self _loadHTMLString:string baseURL:[baseURL _webkit_URLFromURLOrSchemelessFileURL] unreachableURL:nil]; 2582} 2583 2584- (void)loadAlternateHTMLString:(NSString *)string baseURL:(NSURL *)baseURL forUnreachableURL:(NSURL *)unreachableURL 2585{ 2586 WebCoreThreadViolationCheckRoundTwo(); 2587 2588 [self _loadHTMLString:string baseURL:[baseURL _webkit_URLFromURLOrSchemelessFileURL] unreachableURL:[unreachableURL _webkit_URLFromURLOrSchemelessFileURL]]; 2589} 2590 2591- (void)loadArchive:(WebArchive *)archive 2592{ 2593 if (LegacyWebArchive* coreArchive = [archive _coreLegacyWebArchive]) 2594 _private->coreFrame->loader().loadArchive(coreArchive); 2595} 2596 2597- (void)stopLoading 2598{ 2599 if (!_private->coreFrame) 2600 return; 2601 _private->coreFrame->loader().stopForUserCancel(); 2602} 2603 2604- (void)reload 2605{ 2606 _private->coreFrame->loader().reload(false); 2607} 2608 2609- (void)reloadFromOrigin 2610{ 2611 _private->coreFrame->loader().reload(true); 2612} 2613 2614- (WebFrame *)findFrameNamed:(NSString *)name 2615{ 2616 Frame* coreFrame = _private->coreFrame; 2617 if (!coreFrame) 2618 return nil; 2619 return kit(coreFrame->tree().find(name)); 2620} 2621 2622- (WebFrame *)parentFrame 2623{ 2624 Frame* coreFrame = _private->coreFrame; 2625 if (!coreFrame) 2626 return nil; 2627 return [[kit(coreFrame->tree().parent()) retain] autorelease]; 2628} 2629 2630- (NSArray *)childFrames 2631{ 2632 Frame* coreFrame = _private->coreFrame; 2633 if (!coreFrame) 2634 return [NSArray array]; 2635 NSMutableArray *children = [NSMutableArray arrayWithCapacity:coreFrame->tree().childCount()]; 2636 for (Frame* child = coreFrame->tree().firstChild(); child; child = child->tree().nextSibling()) 2637 [children addObject:kit(child)]; 2638 return children; 2639} 2640 2641- (WebScriptObject *)windowObject 2642{ 2643 Frame* coreFrame = _private->coreFrame; 2644 if (!coreFrame) 2645 return 0; 2646 return coreFrame->script().windowScriptObject(); 2647} 2648 2649- (JSGlobalContextRef)globalContext 2650{ 2651 Frame* coreFrame = _private->coreFrame; 2652 if (!coreFrame) 2653 return 0; 2654 return toGlobalRef(coreFrame->script().globalObject(mainThreadNormalWorld())->globalExec()); 2655} 2656 2657#if JSC_OBJC_API_ENABLED 2658- (JSContext *)javaScriptContext 2659{ 2660 Frame* coreFrame = _private->coreFrame; 2661 if (!coreFrame) 2662 return 0; 2663 return coreFrame->script().javaScriptContext(); 2664} 2665#endif 2666 2667@end 2668