WebFrame.mm revision 563af33bc48281d19dce701398dbb88cb54fd7ec
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 Computer, 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 "WebFrameLoaderClient.h" 43#import "WebFrameViewInternal.h" 44#import "WebHTMLView.h" 45#import "WebHTMLViewInternal.h" 46#import "WebIconFetcherInternal.h" 47#import "WebKitStatisticsPrivate.h" 48#import "WebKitVersionChecks.h" 49#import "WebNSURLExtras.h" 50#import "WebScriptDebugger.h" 51#import "WebViewInternal.h" 52#import <JavaScriptCore/APICast.h> 53#import <WebCore/AccessibilityObject.h> 54#import <WebCore/AnimationController.h> 55#import <WebCore/AXObjectCache.h> 56#import <WebCore/ColorMac.h> 57#import <WebCore/DOMImplementation.h> 58#import <WebCore/DocLoader.h> 59#import <WebCore/DocumentFragment.h> 60#import <WebCore/EventHandler.h> 61#import <WebCore/Frame.h> 62#import <WebCore/FrameLoader.h> 63#import <WebCore/FrameTree.h> 64#import <WebCore/GraphicsContext.h> 65#import <WebCore/HTMLFrameOwnerElement.h> 66#import <WebCore/HistoryItem.h> 67#import <WebCore/HitTestResult.h> 68#import <WebCore/LegacyWebArchive.h> 69#import <WebCore/Page.h> 70#import <WebCore/PluginData.h> 71#import <WebCore/RenderPart.h> 72#import <WebCore/RenderView.h> 73#import <WebCore/RenderLayer.h> 74#import <WebCore/ReplaceSelectionCommand.h> 75#import <WebCore/SmartReplace.h> 76#import <WebCore/TextIterator.h> 77#import <WebCore/TypingCommand.h> 78#import <WebCore/htmlediting.h> 79#import <WebCore/ScriptController.h> 80#import <WebCore/ScriptValue.h> 81#import <WebCore/markup.h> 82#import <WebCore/visible_units.h> 83#import <runtime/JSLock.h> 84#import <runtime/JSValue.h> 85#include <wtf/CurrentTime.h> 86 87using namespace std; 88using namespace WebCore; 89using namespace HTMLNames; 90 91using JSC::JSGlobalObject; 92using JSC::JSLock; 93using JSC::JSValuePtr; 94 95/* 96Here is the current behavior matrix for four types of navigations: 97 98Standard Nav: 99 100 Restore form state: YES 101 Restore scroll and focus state: YES 102 Cache policy: NSURLRequestUseProtocolCachePolicy 103 Add to back/forward list: YES 104 105Back/Forward: 106 107 Restore form state: YES 108 Restore scroll and focus state: YES 109 Cache policy: NSURLRequestReturnCacheDataElseLoad 110 Add to back/forward list: NO 111 112Reload (meaning only the reload button): 113 114 Restore form state: NO 115 Restore scroll and focus state: YES 116 Cache policy: NSURLRequestReloadIgnoringCacheData 117 Add to back/forward list: NO 118 119Repeat load of the same URL (by any other means of navigation other than the reload button, including hitting return in the location field): 120 121 Restore form state: NO 122 Restore scroll and focus state: NO, reset to initial conditions 123 Cache policy: NSURLRequestReloadIgnoringCacheData 124 Add to back/forward list: NO 125*/ 126 127NSString *WebPageCacheEntryDateKey = @"WebPageCacheEntryDateKey"; 128NSString *WebPageCacheDataSourceKey = @"WebPageCacheDataSourceKey"; 129NSString *WebPageCacheDocumentViewKey = @"WebPageCacheDocumentViewKey"; 130 131// FIXME: Remove when this key becomes publicly defined 132NSString *NSAccessibilityEnhancedUserInterfaceAttribute = @"AXEnhancedUserInterface"; 133 134@implementation WebFramePrivate 135 136- (void)dealloc 137{ 138 [webFrameView release]; 139 140 delete scriptDebugger; 141 142 [super dealloc]; 143} 144 145- (void)finalize 146{ 147 delete scriptDebugger; 148 149 [super finalize]; 150} 151 152- (void)setWebFrameView:(WebFrameView *)v 153{ 154 [v retain]; 155 [webFrameView release]; 156 webFrameView = v; 157} 158 159@end 160 161CSSStyleDeclaration* core(DOMCSSStyleDeclaration *declaration) 162{ 163 return [declaration _CSSStyleDeclaration]; 164} 165 166DOMCSSStyleDeclaration *kit(WebCore::CSSStyleDeclaration* declaration) 167{ 168 return [DOMCSSStyleDeclaration _wrapCSSStyleDeclaration:declaration]; 169} 170 171Element* core(DOMElement *element) 172{ 173 return [element _element]; 174} 175 176DOMElement *kit(Element* element) 177{ 178 return [DOMElement _wrapElement:element]; 179} 180 181Node* core(DOMNode *node) 182{ 183 return [node _node]; 184} 185 186DOMNode *kit(Node* node) 187{ 188 return [DOMNode _wrapNode:node]; 189} 190 191Document* core(DOMDocument *document) 192{ 193 return [document _document]; 194} 195 196DOMDocument *kit(Document* document) 197{ 198 return [DOMDocument _wrapDocument:document]; 199} 200 201DocumentFragment* core(DOMDocumentFragment *fragment) 202{ 203 return [fragment _documentFragment]; 204} 205 206DOMDocumentFragment *kit(DocumentFragment* fragment) 207{ 208 return [DOMDocumentFragment _wrapDocumentFragment:fragment]; 209} 210 211HTMLElement* core(DOMHTMLElement *element) 212{ 213 return [element _HTMLElement]; 214} 215 216DOMHTMLElement *kit(HTMLElement *element) 217{ 218 return [DOMHTMLElement _wrapHTMLElement:element]; 219} 220 221Range* core(DOMRange *range) 222{ 223 return [range _range]; 224} 225 226DOMRange *kit(Range* range) 227{ 228 return [DOMRange _wrapRange:range]; 229} 230 231EditableLinkBehavior core(WebKitEditableLinkBehavior editableLinkBehavior) 232{ 233 switch (editableLinkBehavior) { 234 case WebKitEditableLinkDefaultBehavior: 235 return EditableLinkDefaultBehavior; 236 case WebKitEditableLinkAlwaysLive: 237 return EditableLinkAlwaysLive; 238 case WebKitEditableLinkOnlyLiveWithShiftKey: 239 return EditableLinkOnlyLiveWithShiftKey; 240 case WebKitEditableLinkLiveWhenNotFocused: 241 return EditableLinkLiveWhenNotFocused; 242 case WebKitEditableLinkNeverLive: 243 return EditableLinkNeverLive; 244 } 245 ASSERT_NOT_REACHED(); 246 return EditableLinkDefaultBehavior; 247} 248 249TextDirectionSubmenuInclusionBehavior core(WebTextDirectionSubmenuInclusionBehavior behavior) 250{ 251 switch (behavior) { 252 case WebTextDirectionSubmenuNeverIncluded: 253 return TextDirectionSubmenuNeverIncluded; 254 case WebTextDirectionSubmenuAutomaticallyIncluded: 255 return TextDirectionSubmenuAutomaticallyIncluded; 256 case WebTextDirectionSubmenuAlwaysIncluded: 257 return TextDirectionSubmenuAlwaysIncluded; 258 } 259 ASSERT_NOT_REACHED(); 260 return TextDirectionSubmenuNeverIncluded; 261} 262 263@implementation WebFrame (WebInternal) 264 265Frame* core(WebFrame *frame) 266{ 267 return frame ? frame->_private->coreFrame : 0; 268} 269 270WebFrame *kit(Frame* frame) 271{ 272 return frame ? static_cast<WebFrameLoaderClient*>(frame->loader()->client())->webFrame() : nil; 273} 274 275Page* core(WebView *webView) 276{ 277 return [webView page]; 278} 279 280WebView *kit(Page* page) 281{ 282 return page ? static_cast<WebChromeClient*>(page->chrome()->client())->webView() : nil; 283} 284 285WebView *getWebView(WebFrame *webFrame) 286{ 287 Frame* coreFrame = core(webFrame); 288 if (!coreFrame) 289 return nil; 290 return kit(coreFrame->page()); 291} 292 293+ (PassRefPtr<Frame>)_createFrameWithPage:(Page*)page frameName:(const String&)name frameView:(WebFrameView *)frameView ownerElement:(HTMLFrameOwnerElement*)ownerElement 294{ 295 WebView *webView = kit(page); 296 297 WebFrame *frame = [[self alloc] _initWithWebFrameView:frameView webView:webView]; 298 RefPtr<Frame> coreFrame = Frame::create(page, ownerElement, new WebFrameLoaderClient(frame)); 299 [frame release]; 300 frame->_private->coreFrame = coreFrame.get(); 301 302 coreFrame->tree()->setName(name); 303 if (ownerElement) { 304 ASSERT(ownerElement->document()->frame()); 305 ownerElement->document()->frame()->tree()->appendChild(coreFrame.get()); 306 } 307 308 coreFrame->init(); 309 310 [webView _setZoomMultiplier:[webView _realZoomMultiplier] isTextOnly:[webView _realZoomMultiplierIsTextOnly]]; 311 312 return coreFrame.release(); 313} 314 315+ (void)_createMainFrameWithPage:(Page*)page frameName:(const String&)name frameView:(WebFrameView *)frameView 316{ 317 [self _createFrameWithPage:page frameName:name frameView:frameView ownerElement:0]; 318} 319 320+ (PassRefPtr<WebCore::Frame>)_createSubframeWithOwnerElement:(HTMLFrameOwnerElement*)ownerElement frameName:(const String&)name frameView:(WebFrameView *)frameView 321{ 322 return [self _createFrameWithPage:ownerElement->document()->frame()->page() frameName:name frameView:frameView ownerElement:ownerElement]; 323} 324 325- (void)_attachScriptDebugger 326{ 327 ScriptController* scriptController = _private->coreFrame->script(); 328 329 // Calling ScriptController::globalObject() would create a window shell, and dispatch corresponding callbacks, which may be premature 330 // if the script debugger is attached before a document is created. 331 if (!scriptController->haveWindowShell()) 332 return; 333 334 JSGlobalObject* globalObject = scriptController->globalObject(); 335 if (!globalObject) 336 return; 337 338 if (_private->scriptDebugger) { 339 ASSERT(_private->scriptDebugger == globalObject->debugger()); 340 return; 341 } 342 343 _private->scriptDebugger = new WebScriptDebugger(globalObject); 344} 345 346- (void)_detachScriptDebugger 347{ 348 if (!_private->scriptDebugger) 349 return; 350 351 delete _private->scriptDebugger; 352 _private->scriptDebugger = 0; 353} 354 355- (id)_initWithWebFrameView:(WebFrameView *)fv webView:(WebView *)v 356{ 357 self = [super init]; 358 if (!self) 359 return nil; 360 361 _private = [[WebFramePrivate alloc] init]; 362 363 if (fv) { 364 [_private setWebFrameView:fv]; 365 [fv _setWebFrame:self]; 366 } 367 368 _private->shouldCreateRenderers = YES; 369 370 ++WebFrameCount; 371 372 return self; 373} 374 375- (void)_clearCoreFrame 376{ 377 _private->coreFrame = 0; 378} 379 380- (void)_updateBackgroundAndUpdatesWhileOffscreen 381{ 382 WebView *webView = getWebView(self); 383 BOOL drawsBackground = [webView drawsBackground]; 384 NSColor *backgroundColor = [webView backgroundColor]; 385 386 Frame* coreFrame = _private->coreFrame; 387 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) { 388 WebFrame *webFrame = kit(frame); 389 // Don't call setDrawsBackground:YES here because it may be NO because of a load 390 // in progress; WebFrameLoaderClient keeps it set to NO during the load process. 391 if (!drawsBackground) 392 [[[webFrame frameView] _scrollView] setDrawsBackground:NO]; 393 [[[webFrame frameView] _scrollView] setBackgroundColor:backgroundColor]; 394 id documentView = [[webFrame frameView] documentView]; 395 if ([documentView respondsToSelector:@selector(setDrawsBackground:)]) 396 [documentView setDrawsBackground:drawsBackground]; 397 if ([documentView respondsToSelector:@selector(setBackgroundColor:)]) 398 [documentView setBackgroundColor:backgroundColor]; 399 if (frame && frame->view()) { 400 frame->view()->setTransparent(!drawsBackground); 401 Color color = colorFromNSColor([backgroundColor colorUsingColorSpaceName:NSDeviceRGBColorSpace]); 402 frame->view()->setBaseBackgroundColor(color); 403 frame->view()->setShouldUpdateWhileOffscreen([webView shouldUpdateWhileOffscreen]); 404 } 405 } 406} 407 408- (void)_setInternalLoadDelegate:(id)internalLoadDelegate 409{ 410 _private->internalLoadDelegate = internalLoadDelegate; 411} 412 413- (id)_internalLoadDelegate 414{ 415 return _private->internalLoadDelegate; 416} 417 418#ifndef BUILDING_ON_TIGER 419- (void)_unmarkAllBadGrammar 420{ 421 Frame* coreFrame = _private->coreFrame; 422 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) { 423 if (Document* document = frame->document()) 424 document->removeMarkers(DocumentMarker::Grammar); 425 } 426} 427#endif 428 429- (void)_unmarkAllMisspellings 430{ 431 Frame* coreFrame = _private->coreFrame; 432 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) { 433 if (Document* document = frame->document()) 434 document->removeMarkers(DocumentMarker::Spelling); 435 } 436} 437 438- (BOOL)_hasSelection 439{ 440 id documentView = [_private->webFrameView documentView]; 441 442 // optimization for common case to avoid creating potentially large selection string 443 if ([documentView isKindOfClass:[WebHTMLView class]]) 444 if (Frame* coreFrame = _private->coreFrame) 445 return coreFrame->selection()->isRange(); 446 447 if ([documentView conformsToProtocol:@protocol(WebDocumentText)]) 448 return [[documentView selectedString] length] > 0; 449 450 return NO; 451} 452 453- (void)_clearSelection 454{ 455 id documentView = [_private->webFrameView documentView]; 456 if ([documentView conformsToProtocol:@protocol(WebDocumentText)]) 457 [documentView deselectAll]; 458} 459 460#if !ASSERT_DISABLED 461- (BOOL)_atMostOneFrameHasSelection 462{ 463 // FIXME: 4186050 is one known case that makes this debug check fail. 464 BOOL found = NO; 465 Frame* coreFrame = _private->coreFrame; 466 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) 467 if ([kit(frame) _hasSelection]) { 468 if (found) 469 return NO; 470 found = YES; 471 } 472 return YES; 473} 474#endif 475 476- (WebFrame *)_findFrameWithSelection 477{ 478 Frame* coreFrame = _private->coreFrame; 479 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) { 480 WebFrame *webFrame = kit(frame); 481 if ([webFrame _hasSelection]) 482 return webFrame; 483 } 484 return nil; 485} 486 487- (void)_clearSelectionInOtherFrames 488{ 489 // We rely on WebDocumentSelection protocol implementors to call this method when they become first 490 // responder. It would be nicer to just notice first responder changes here instead, but there's no 491 // notification sent when the first responder changes in general (Radar 2573089). 492 WebFrame *frameWithSelection = [[getWebView(self) mainFrame] _findFrameWithSelection]; 493 if (frameWithSelection != self) 494 [frameWithSelection _clearSelection]; 495 496 // While we're in the general area of selection and frames, check that there is only one now. 497 ASSERT([[getWebView(self) mainFrame] _atMostOneFrameHasSelection]); 498} 499 500static inline WebDataSource *dataSource(DocumentLoader* loader) 501{ 502 return loader ? static_cast<WebDocumentLoaderMac*>(loader)->dataSource() : nil; 503} 504 505- (WebDataSource *)_dataSource 506{ 507 return dataSource(_private->coreFrame->loader()->documentLoader()); 508} 509 510- (void)_addData:(NSData *)data 511{ 512 Document* document = _private->coreFrame->document(); 513 514 // Document may be nil if the part is about to redirect 515 // as a result of JS executing during load, i.e. one frame 516 // changing another's location before the frame's document 517 // has been created. 518 if (!document) 519 return; 520 521 document->setShouldCreateRenderers(_private->shouldCreateRenderers); 522 _private->coreFrame->loader()->addData((const char *)[data bytes], [data length]); 523} 524 525- (NSString *)_stringWithDocumentTypeStringAndMarkupString:(NSString *)markupString 526{ 527 return _private->coreFrame->documentTypeString() + markupString; 528} 529 530- (NSArray *)_nodesFromList:(Vector<Node*> *)nodesVector 531{ 532 size_t size = nodesVector->size(); 533 NSMutableArray *nodes = [NSMutableArray arrayWithCapacity:size]; 534 for (size_t i = 0; i < size; ++i) 535 [nodes addObject:[DOMNode _wrapNode:(*nodesVector)[i]]]; 536 return nodes; 537} 538 539- (NSString *)_markupStringFromRange:(DOMRange *)range nodes:(NSArray **)nodes 540{ 541 // FIXME: This is always "for interchange". Is that right? See the previous method. 542 Vector<Node*> nodeList; 543 NSString *markupString = createMarkup([range _range], nodes ? &nodeList : 0, AnnotateForInterchange); 544 if (nodes) 545 *nodes = [self _nodesFromList:&nodeList]; 546 547 return [self _stringWithDocumentTypeStringAndMarkupString:markupString]; 548} 549 550- (NSString *)_selectedString 551{ 552 return _private->coreFrame->displayStringModifiedByEncoding(_private->coreFrame->selectedText()); 553} 554 555- (NSString *)_stringForRange:(DOMRange *)range 556{ 557 // This will give a system malloc'd buffer that can be turned directly into an NSString 558 unsigned length; 559 UChar* buf = plainTextToMallocAllocatedBuffer([range _range], length, true); 560 561 if (!buf) 562 return [NSString string]; 563 564 // Transfer buffer ownership to NSString 565 return [[[NSString alloc] initWithCharactersNoCopy:buf length:length freeWhenDone:YES] autorelease]; 566} 567 568- (void)_drawRect:(NSRect)rect contentsOnly:(BOOL)contentsOnly 569{ 570 PlatformGraphicsContext* platformContext = static_cast<PlatformGraphicsContext*>([[NSGraphicsContext currentContext] graphicsPort]); 571 ASSERT([[NSGraphicsContext currentContext] isFlipped]); 572 GraphicsContext context(platformContext); 573 574 if (contentsOnly) 575 _private->coreFrame->view()->paintContents(&context, enclosingIntRect(rect)); 576 else 577 _private->coreFrame->view()->paint(&context, enclosingIntRect(rect)); 578} 579 580// Used by pagination code called from AppKit when a standalone web page is printed. 581- (NSArray*)_computePageRectsWithPrintWidthScaleFactor:(float)printWidthScaleFactor printHeight:(float)printHeight 582{ 583 NSMutableArray* pages = [NSMutableArray arrayWithCapacity:5]; 584 if (printWidthScaleFactor <= 0) { 585 LOG_ERROR("printWidthScaleFactor has bad value %.2f", printWidthScaleFactor); 586 return pages; 587 } 588 589 if (printHeight <= 0) { 590 LOG_ERROR("printHeight has bad value %.2f", printHeight); 591 return pages; 592 } 593 594 if (!_private->coreFrame || !_private->coreFrame->document() || !_private->coreFrame->view()) return pages; 595 RenderView* root = static_cast<RenderView *>(_private->coreFrame->document()->renderer()); 596 if (!root) return pages; 597 598 FrameView* view = _private->coreFrame->view(); 599 if (!view) 600 return pages; 601 602 NSView* documentView = view->documentView(); 603 if (!documentView) 604 return pages; 605 606 float currPageHeight = printHeight; 607 float docHeight = root->layer()->height(); 608 float docWidth = root->layer()->width(); 609 float printWidth = docWidth/printWidthScaleFactor; 610 611 // We need to give the part the opportunity to adjust the page height at each step. 612 for (float i = 0; i < docHeight; i += currPageHeight) { 613 float proposedBottom = min(docHeight, i + printHeight); 614 view->adjustPageHeight(&proposedBottom, i, proposedBottom, i); 615 currPageHeight = max(1.0f, proposedBottom - i); 616 for (float j = 0; j < docWidth; j += printWidth) { 617 NSValue* val = [NSValue valueWithRect: NSMakeRect(j, i, printWidth, currPageHeight)]; 618 [pages addObject: val]; 619 } 620 } 621 622 return pages; 623} 624 625- (BOOL)_getVisibleRect:(NSRect*)rect 626{ 627 ASSERT_ARG(rect, rect); 628 if (RenderPart* ownerRenderer = _private->coreFrame->ownerRenderer()) { 629 if (ownerRenderer->needsLayout()) 630 return NO; 631 *rect = ownerRenderer->absoluteClippedOverflowRect(); 632 return YES; 633 } 634 635 return NO; 636} 637 638- (NSString *)_stringByEvaluatingJavaScriptFromString:(NSString *)string 639{ 640 return [self _stringByEvaluatingJavaScriptFromString:string forceUserGesture:true]; 641} 642 643- (NSString *)_stringByEvaluatingJavaScriptFromString:(NSString *)string forceUserGesture:(BOOL)forceUserGesture 644{ 645 ASSERT(_private->coreFrame->document()); 646 647 JSValuePtr result = _private->coreFrame->loader()->executeScript(string, forceUserGesture).jsValue(); 648 649 if (!_private->coreFrame) // In case the script removed our frame from the page. 650 return @""; 651 652 // This bizarre set of rules matches behavior from WebKit for Safari 2.0. 653 // If you don't like it, use -[WebScriptObject evaluateWebScript:] or 654 // JSEvaluateScript instead, since they have less surprising semantics. 655 if (!result || !result.isBoolean() && !result.isString() && !result.isNumber()) 656 return @""; 657 658 JSLock lock(false); 659 return String(result.toString(_private->coreFrame->script()->globalObject()->globalExec())); 660} 661 662- (NSRect)_caretRectAtNode:(DOMNode *)node offset:(int)offset affinity:(NSSelectionAffinity)affinity 663{ 664 VisiblePosition visiblePosition([node _node], offset, static_cast<EAffinity>(affinity)); 665 return visiblePosition.absoluteCaretBounds(); 666} 667 668- (NSRect)_firstRectForDOMRange:(DOMRange *)range 669{ 670 return _private->coreFrame->firstRectForRange([range _range]); 671} 672 673- (void)_scrollDOMRangeToVisible:(DOMRange *)range 674{ 675 NSRect rangeRect = [self _firstRectForDOMRange:range]; 676 Node *startNode = [[range startContainer] _node]; 677 678 if (startNode && startNode->renderer()) { 679 RenderLayer *layer = startNode->renderer()->enclosingLayer(); 680 if (layer) 681 layer->scrollRectToVisible(enclosingIntRect(rangeRect), false, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded); 682 } 683} 684 685- (BOOL)_needsLayout 686{ 687 return _private->coreFrame->view() ? _private->coreFrame->view()->needsLayout() : false; 688} 689 690- (id)_accessibilityTree 691{ 692#if HAVE(ACCESSIBILITY) 693 if (!AXObjectCache::accessibilityEnabled()) { 694 AXObjectCache::enableAccessibility(); 695 if ([[NSApp accessibilityAttributeValue:NSAccessibilityEnhancedUserInterfaceAttribute] boolValue]) 696 AXObjectCache::enableEnhancedUserInterfaceAccessibility(); 697 } 698 699 if (!_private->coreFrame || !_private->coreFrame->document()) 700 return nil; 701 RenderView* root = static_cast<RenderView *>(_private->coreFrame->document()->renderer()); 702 if (!root) 703 return nil; 704 return _private->coreFrame->document()->axObjectCache()->getOrCreate(root)->wrapper(); 705#else 706 return nil; 707#endif 708} 709 710- (DOMRange *)_rangeByAlteringCurrentSelection:(SelectionController::EAlteration)alteration direction:(SelectionController::EDirection)direction granularity:(TextGranularity)granularity 711{ 712 if (_private->coreFrame->selection()->isNone()) 713 return nil; 714 715 SelectionController selection; 716 selection.setSelection(_private->coreFrame->selection()->selection()); 717 selection.modify(alteration, direction, granularity); 718 return [DOMRange _wrapRange:selection.toNormalizedRange().get()]; 719} 720 721- (TextGranularity)_selectionGranularity 722{ 723 return _private->coreFrame->selectionGranularity(); 724} 725 726- (NSRange)_convertToNSRange:(Range *)range 727{ 728 if (!range || !range->startContainer()) 729 return NSMakeRange(NSNotFound, 0); 730 731 Element* selectionRoot = _private->coreFrame->selection()->rootEditableElement(); 732 Element* scope = selectionRoot ? selectionRoot : _private->coreFrame->document()->documentElement(); 733 734 // Mouse events may cause TSM to attempt to create an NSRange for a portion of the view 735 // that is not inside the current editable region. These checks ensure we don't produce 736 // potentially invalid data when responding to such requests. 737 if (range->startContainer() != scope && !range->startContainer()->isDescendantOf(scope)) 738 return NSMakeRange(NSNotFound, 0); 739 if (range->endContainer() != scope && !range->endContainer()->isDescendantOf(scope)) 740 return NSMakeRange(NSNotFound, 0); 741 742 RefPtr<Range> testRange = Range::create(scope->document(), scope, 0, range->startContainer(), range->startOffset()); 743 ASSERT(testRange->startContainer() == scope); 744 int startPosition = TextIterator::rangeLength(testRange.get()); 745 746 ExceptionCode ec; 747 testRange->setEnd(range->endContainer(), range->endOffset(), ec); 748 ASSERT(testRange->startContainer() == scope); 749 int endPosition = TextIterator::rangeLength(testRange.get()); 750 751 return NSMakeRange(startPosition, endPosition - startPosition); 752} 753 754- (PassRefPtr<Range>)_convertToDOMRange:(NSRange)nsrange 755{ 756 if (nsrange.location > INT_MAX) 757 return 0; 758 if (nsrange.length > INT_MAX || nsrange.location + nsrange.length > INT_MAX) 759 nsrange.length = INT_MAX - nsrange.location; 760 761 // our critical assumption is that we are only called by input methods that 762 // concentrate on a given area containing the selection 763 // We have to do this because of text fields and textareas. The DOM for those is not 764 // directly in the document DOM, so serialization is problematic. Our solution is 765 // to use the root editable element of the selection start as the positional base. 766 // That fits with AppKit's idea of an input context. 767 Element* selectionRoot = _private->coreFrame->selection()->rootEditableElement(); 768 Element* scope = selectionRoot ? selectionRoot : _private->coreFrame->document()->documentElement(); 769 return TextIterator::rangeFromLocationAndLength(scope, nsrange.location, nsrange.length); 770} 771 772- (DOMRange *)convertNSRangeToDOMRange:(NSRange)nsrange 773{ 774 // This method exists to maintain compatibility with Leopard's Dictionary.app. <rdar://problem/6002160> 775 return [self _convertNSRangeToDOMRange:nsrange]; 776} 777 778- (DOMRange *)_convertNSRangeToDOMRange:(NSRange)nsrange 779{ 780 return [DOMRange _wrapRange:[self _convertToDOMRange:nsrange].get()]; 781} 782 783- (NSRange)convertDOMRangeToNSRange:(DOMRange *)range 784{ 785 // This method exists to maintain compatibility with Leopard's Dictionary.app. <rdar://problem/6002160> 786 return [self _convertDOMRangeToNSRange:range]; 787} 788 789- (NSRange)_convertDOMRangeToNSRange:(DOMRange *)range 790{ 791 return [self _convertToNSRange:[range _range]]; 792} 793 794- (DOMRange *)_markDOMRange 795{ 796 return [DOMRange _wrapRange:_private->coreFrame->mark().toNormalizedRange().get()]; 797} 798 799// Given proposedRange, returns an extended range that includes adjacent whitespace that should 800// be deleted along with the proposed range in order to preserve proper spacing and punctuation of 801// the text surrounding the deletion. 802- (DOMRange *)_smartDeleteRangeForProposedRange:(DOMRange *)proposedRange 803{ 804 Node *startContainer = [[proposedRange startContainer] _node]; 805 Node *endContainer = [[proposedRange endContainer] _node]; 806 if (startContainer == nil || endContainer == nil) 807 return nil; 808 809 ASSERT(startContainer->document() == endContainer->document()); 810 811 _private->coreFrame->document()->updateLayoutIgnorePendingStylesheets(); 812 813 Position start(startContainer, [proposedRange startOffset]); 814 Position end(endContainer, [proposedRange endOffset]); 815 Position newStart = start.upstream().leadingWhitespacePosition(DOWNSTREAM, true); 816 if (newStart.isNull()) 817 newStart = start; 818 Position newEnd = end.downstream().trailingWhitespacePosition(DOWNSTREAM, true); 819 if (newEnd.isNull()) 820 newEnd = end; 821 822 newStart = rangeCompliantEquivalent(newStart); 823 newEnd = rangeCompliantEquivalent(newEnd); 824 825 RefPtr<Range> range = _private->coreFrame->document()->createRange(); 826 int exception = 0; 827 range->setStart(newStart.node(), newStart.m_offset, exception); 828 range->setEnd(newStart.node(), newStart.m_offset, exception); 829 return [DOMRange _wrapRange:range.get()]; 830} 831 832// Determines whether whitespace needs to be added around aString to preserve proper spacing and 833// punctuation when it’s inserted into the receiver’s text over charRange. Returns by reference 834// in beforeString and afterString any whitespace that should be added, unless either or both are 835// nil. Both are returned as nil if aString is nil or if smart insertion and deletion are disabled. 836- (void)_smartInsertForString:(NSString *)pasteString replacingRange:(DOMRange *)rangeToReplace beforeString:(NSString **)beforeString afterString:(NSString **)afterString 837{ 838 // give back nil pointers in case of early returns 839 if (beforeString) 840 *beforeString = nil; 841 if (afterString) 842 *afterString = nil; 843 844 // inspect destination 845 Node *startContainer = [[rangeToReplace startContainer] _node]; 846 Node *endContainer = [[rangeToReplace endContainer] _node]; 847 848 Position startPos(startContainer, [rangeToReplace startOffset]); 849 Position endPos(endContainer, [rangeToReplace endOffset]); 850 851 VisiblePosition startVisiblePos = VisiblePosition(startPos, VP_DEFAULT_AFFINITY); 852 VisiblePosition endVisiblePos = VisiblePosition(endPos, VP_DEFAULT_AFFINITY); 853 854 // this check also ensures startContainer, startPos, endContainer, and endPos are non-null 855 if (startVisiblePos.isNull() || endVisiblePos.isNull()) 856 return; 857 858 bool addLeadingSpace = startPos.leadingWhitespacePosition(VP_DEFAULT_AFFINITY, true).isNull() && !isStartOfParagraph(startVisiblePos); 859 if (addLeadingSpace) 860 if (UChar previousChar = startVisiblePos.previous().characterAfter()) 861 addLeadingSpace = !isCharacterSmartReplaceExempt(previousChar, true); 862 863 bool addTrailingSpace = endPos.trailingWhitespacePosition(VP_DEFAULT_AFFINITY, true).isNull() && !isEndOfParagraph(endVisiblePos); 864 if (addTrailingSpace) 865 if (UChar thisChar = endVisiblePos.characterAfter()) 866 addTrailingSpace = !isCharacterSmartReplaceExempt(thisChar, false); 867 868 // inspect source 869 bool hasWhitespaceAtStart = false; 870 bool hasWhitespaceAtEnd = false; 871 unsigned pasteLength = [pasteString length]; 872 if (pasteLength > 0) { 873 NSCharacterSet *whiteSet = [NSCharacterSet whitespaceAndNewlineCharacterSet]; 874 875 if ([whiteSet characterIsMember:[pasteString characterAtIndex:0]]) { 876 hasWhitespaceAtStart = YES; 877 } 878 if ([whiteSet characterIsMember:[pasteString characterAtIndex:(pasteLength - 1)]]) { 879 hasWhitespaceAtEnd = YES; 880 } 881 } 882 883 // issue the verdict 884 if (beforeString && addLeadingSpace && !hasWhitespaceAtStart) 885 *beforeString = @" "; 886 if (afterString && addTrailingSpace && !hasWhitespaceAtEnd) 887 *afterString = @" "; 888} 889 890- (DOMDocumentFragment *)_documentFragmentWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString 891{ 892 if (!_private->coreFrame || !_private->coreFrame->document()) 893 return 0; 894 895 return [DOMDocumentFragment _wrapDocumentFragment:createFragmentFromMarkup(_private->coreFrame->document(), markupString, baseURLString).get()]; 896} 897 898- (DOMDocumentFragment *)_documentFragmentWithNodesAsParagraphs:(NSArray *)nodes 899{ 900 if (!_private->coreFrame || !_private->coreFrame->document()) 901 return 0; 902 903 NSEnumerator *nodeEnum = [nodes objectEnumerator]; 904 Vector<Node*> nodesVector; 905 DOMNode *node; 906 while ((node = [nodeEnum nextObject])) 907 nodesVector.append([node _node]); 908 909 return [DOMDocumentFragment _wrapDocumentFragment:createFragmentFromNodes(_private->coreFrame->document(), nodesVector).get()]; 910} 911 912- (void)_replaceSelectionWithNode:(DOMNode *)node selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle 913{ 914 DOMDocumentFragment *fragment = [DOMDocumentFragment _wrapDocumentFragment:_private->coreFrame->document()->createDocumentFragment().get()]; 915 [fragment appendChild:node]; 916 [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:matchStyle]; 917} 918 919- (void)_insertParagraphSeparatorInQuotedContent 920{ 921 if (_private->coreFrame->selection()->isNone()) 922 return; 923 924 TypingCommand::insertParagraphSeparatorInQuotedContent(_private->coreFrame->document()); 925 _private->coreFrame->revealSelection(ScrollAlignment::alignToEdgeIfNeeded); 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 VisiblePosition position = [self _visiblePositionForPoint:point]; 937 if (position.isNull()) 938 return nil; 939 940 VisiblePosition previous = position.previous(); 941 if (previous.isNotNull()) { 942 DOMRange *previousCharacterRange = [DOMRange _wrapRange:makeRange(previous, position).get()]; 943 NSRect rect = [self _firstRectForDOMRange:previousCharacterRange]; 944 if (NSPointInRect(point, rect)) 945 return previousCharacterRange; 946 } 947 948 VisiblePosition next = position.next(); 949 if (next.isNotNull()) { 950 DOMRange *nextCharacterRange = [DOMRange _wrapRange:makeRange(position, next).get()]; 951 NSRect rect = [self _firstRectForDOMRange:nextCharacterRange]; 952 if (NSPointInRect(point, rect)) 953 return nextCharacterRange; 954 } 955 956 return nil; 957} 958 959- (DOMCSSStyleDeclaration *)_typingStyle 960{ 961 if (!_private->coreFrame || !_private->coreFrame->typingStyle()) 962 return nil; 963 return [DOMCSSStyleDeclaration _wrapCSSStyleDeclaration:_private->coreFrame->typingStyle()->copy().get()]; 964} 965 966- (void)_setTypingStyle:(DOMCSSStyleDeclaration *)style withUndoAction:(EditAction)undoAction 967{ 968 if (!_private->coreFrame) 969 return; 970 _private->coreFrame->computeAndSetTypingStyle([style _CSSStyleDeclaration], undoAction); 971} 972 973- (void)_dragSourceMovedTo:(NSPoint)windowLoc 974{ 975 if (!_private->coreFrame) 976 return; 977 FrameView* view = _private->coreFrame->view(); 978 if (!view) 979 return; 980 // FIXME: These are fake modifier keys here, but they should be real ones instead. 981 PlatformMouseEvent event(IntPoint(windowLoc), globalPoint(windowLoc, [view->platformWidget() window]), 982 LeftButton, MouseEventMoved, 0, false, false, false, false, currentTime()); 983 _private->coreFrame->eventHandler()->dragSourceMovedTo(event); 984} 985 986- (void)_dragSourceEndedAt:(NSPoint)windowLoc operation:(NSDragOperation)operation 987{ 988 if (!_private->coreFrame) 989 return; 990 FrameView* view = _private->coreFrame->view(); 991 if (!view) 992 return; 993 // FIXME: These are fake modifier keys here, but they should be real ones instead. 994 PlatformMouseEvent event(IntPoint(windowLoc), globalPoint(windowLoc, [view->platformWidget() window]), 995 LeftButton, MouseEventMoved, 0, false, false, false, false, currentTime()); 996 _private->coreFrame->eventHandler()->dragSourceEndedAt(event, (DragOperation)operation); 997} 998 999- (BOOL)_canProvideDocumentSource 1000{ 1001 Frame* frame = _private->coreFrame; 1002 String mimeType = frame->loader()->responseMIMEType(); 1003 PluginData* pluginData = frame->page() ? frame->page()->pluginData() : 0; 1004 1005 if (WebCore::DOMImplementation::isTextMIMEType(mimeType) || 1006 Image::supportsType(mimeType) || 1007 (pluginData && pluginData->supportsMimeType(mimeType))) 1008 return NO; 1009 1010 return YES; 1011} 1012 1013- (BOOL)_canSaveAsWebArchive 1014{ 1015 // Currently, all documents that we can view source for 1016 // (HTML and XML documents) can also be saved as web archives 1017 return [self _canProvideDocumentSource]; 1018} 1019 1020- (void)_receivedData:(NSData *)data textEncodingName:(NSString *)textEncodingName 1021{ 1022 // Set the encoding. This only needs to be done once, but it's harmless to do it again later. 1023 String encoding = _private->coreFrame->loader()->documentLoader()->overrideEncoding(); 1024 bool userChosen = !encoding.isNull(); 1025 if (encoding.isNull()) 1026 encoding = textEncodingName; 1027 _private->coreFrame->loader()->setEncoding(encoding, userChosen); 1028 [self _addData:data]; 1029} 1030 1031@end 1032 1033@implementation WebFrame (WebPrivate) 1034 1035// FIXME: This exists only as a convenience for Safari, consider moving there. 1036- (BOOL)_isDescendantOfFrame:(WebFrame *)ancestor 1037{ 1038 Frame* coreFrame = _private->coreFrame; 1039 return coreFrame && coreFrame->tree()->isDescendantOf(core(ancestor)); 1040} 1041 1042- (void)_setShouldCreateRenderers:(BOOL)shouldCreateRenderers 1043{ 1044 _private->shouldCreateRenderers = shouldCreateRenderers; 1045} 1046 1047- (NSColor *)_bodyBackgroundColor 1048{ 1049 Document* document = _private->coreFrame->document(); 1050 if (!document) 1051 return nil; 1052 HTMLElement* body = document->body(); 1053 if (!body) 1054 return nil; 1055 RenderObject* bodyRenderer = body->renderer(); 1056 if (!bodyRenderer) 1057 return nil; 1058 Color color = bodyRenderer->style()->backgroundColor(); 1059 if (!color.isValid()) 1060 return nil; 1061 return nsColor(color); 1062} 1063 1064- (BOOL)_isFrameSet 1065{ 1066 Document* document = _private->coreFrame->document(); 1067 return document && document->isFrameSet(); 1068} 1069 1070- (BOOL)_firstLayoutDone 1071{ 1072 return _private->coreFrame->loader()->firstLayoutDone(); 1073} 1074 1075- (WebFrameLoadType)_loadType 1076{ 1077 return (WebFrameLoadType)_private->coreFrame->loader()->loadType(); 1078} 1079 1080- (NSRange)_selectedNSRange 1081{ 1082 return [self _convertToNSRange:_private->coreFrame->selection()->toNormalizedRange().get()]; 1083} 1084 1085- (void)_selectNSRange:(NSRange)range 1086{ 1087 RefPtr<Range> domRange = [self _convertToDOMRange:range]; 1088 if (domRange) 1089 _private->coreFrame->selection()->setSelection(VisibleSelection(domRange.get(), SEL_DEFAULT_AFFINITY)); 1090} 1091 1092- (BOOL)_isDisplayingStandaloneImage 1093{ 1094 Document* document = _private->coreFrame->document(); 1095 return document && document->isImageDocument(); 1096} 1097 1098- (unsigned)_pendingFrameUnloadEventCount 1099{ 1100 return _private->coreFrame->eventHandler()->pendingFrameUnloadEventCount(); 1101} 1102 1103- (WebIconFetcher *)fetchApplicationIcon:(id)target 1104 selector:(SEL)selector 1105{ 1106 return [WebIconFetcher _fetchApplicationIconForFrame:self 1107 target:target 1108 selector:selector]; 1109} 1110 1111- (void)_setIsDisconnected:(bool)isDisconnected 1112{ 1113 _private->coreFrame->setIsDisconnected(isDisconnected); 1114} 1115 1116- (void)_setExcludeFromTextSearch:(bool)exclude 1117{ 1118 _private->coreFrame->setExcludeFromTextSearch(exclude); 1119} 1120 1121#if ENABLE(NETSCAPE_PLUGIN_API) 1122- (void)_recursive_resumeNullEventsForAllNetscapePlugins 1123{ 1124 Frame* coreFrame = core(self); 1125 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) { 1126 NSView <WebDocumentView> *documentView = [[kit(frame) frameView] documentView]; 1127 if ([documentView isKindOfClass:[WebHTMLView class]]) 1128 [(WebHTMLView *)documentView _resumeNullEventsForAllNetscapePlugins]; 1129 } 1130} 1131 1132- (void)_recursive_pauseNullEventsForAllNetscapePlugins 1133{ 1134 Frame* coreFrame = core(self); 1135 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) { 1136 NSView <WebDocumentView> *documentView = [[kit(frame) frameView] documentView]; 1137 if ([documentView isKindOfClass:[WebHTMLView class]]) 1138 [(WebHTMLView *)documentView _pauseNullEventsForAllNetscapePlugins]; 1139 } 1140} 1141#endif 1142 1143- (BOOL)_pauseAnimation:(NSString*)name onNode:(DOMNode *)node atTime:(NSTimeInterval)time 1144{ 1145 Frame* frame = core(self); 1146 if (!frame) 1147 return false; 1148 1149 AnimationController* controller = frame->animation(); 1150 if (!controller) 1151 return false; 1152 1153 Node* coreNode = [node _node]; 1154 if (!coreNode || !coreNode->renderer()) 1155 return false; 1156 1157 return controller->pauseAnimationAtTime(coreNode->renderer(), name, time); 1158} 1159 1160- (BOOL)_pauseTransitionOfProperty:(NSString*)name onNode:(DOMNode*)node atTime:(NSTimeInterval)time 1161{ 1162 Frame* frame = core(self); 1163 if (!frame) 1164 return false; 1165 1166 AnimationController* controller = frame->animation(); 1167 if (!controller) 1168 return false; 1169 1170 Node* coreNode = [node _node]; 1171 if (!coreNode || !coreNode->renderer()) 1172 return false; 1173 1174 return controller->pauseTransitionAtTime(coreNode->renderer(), name, time); 1175} 1176 1177- (unsigned) _numberOfActiveAnimations 1178{ 1179 Frame* frame = core(self); 1180 if (!frame) 1181 return false; 1182 1183 AnimationController* controller = frame->animation(); 1184 if (!controller) 1185 return false; 1186 1187 return controller->numberOfActiveAnimations(); 1188} 1189 1190- (void)_replaceSelectionWithFragment:(DOMDocumentFragment *)fragment selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle 1191{ 1192 if (_private->coreFrame->selection()->isNone() || !fragment) 1193 return; 1194 1195 applyCommand(ReplaceSelectionCommand::create(_private->coreFrame->document(), [fragment _documentFragment], selectReplacement, smartReplace, matchStyle)); 1196 _private->coreFrame->revealSelection(ScrollAlignment::alignToEdgeIfNeeded); 1197} 1198 1199- (void)_replaceSelectionWithText:(NSString *)text selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace 1200{ 1201 DOMDocumentFragment* fragment = kit(createFragmentFromText(_private->coreFrame->selection()->toNormalizedRange().get(), text).get()); 1202 [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:YES]; 1203} 1204 1205- (void)_replaceSelectionWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace 1206{ 1207 DOMDocumentFragment *fragment = [self _documentFragmentWithMarkupString:markupString baseURLString:baseURLString]; 1208 [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:NO]; 1209} 1210 1211@end 1212 1213@implementation WebFrame 1214 1215- (id)init 1216{ 1217 return nil; 1218} 1219 1220// Should be deprecated. 1221- (id)initWithName:(NSString *)name webFrameView:(WebFrameView *)view webView:(WebView *)webView 1222{ 1223 return nil; 1224} 1225 1226- (void)dealloc 1227{ 1228 [_private release]; 1229 --WebFrameCount; 1230 [super dealloc]; 1231} 1232 1233- (void)finalize 1234{ 1235 --WebFrameCount; 1236 [super finalize]; 1237} 1238 1239- (NSString *)name 1240{ 1241 Frame* coreFrame = _private->coreFrame; 1242 if (!coreFrame) 1243 return nil; 1244 return coreFrame->tree()->name(); 1245} 1246 1247- (WebFrameView *)frameView 1248{ 1249 return _private->webFrameView; 1250} 1251 1252- (WebView *)webView 1253{ 1254 return getWebView(self); 1255} 1256 1257- (DOMDocument *)DOMDocument 1258{ 1259 Frame* coreFrame = _private->coreFrame; 1260 if (!coreFrame) 1261 return nil; 1262 1263 // FIXME: <rdar://problem/5145841> When loading a custom view/representation 1264 // into a web frame, the old document can still be around. This makes sure that 1265 // we'll return nil in those cases. 1266 if (![[self _dataSource] _isDocumentHTML]) 1267 return nil; 1268 1269 Document* document = coreFrame->document(); 1270 1271 // According to the documentation, we should return nil if the frame doesn't have a document. 1272 // While full-frame images and plugins do have an underlying HTML document, we return nil here to be 1273 // backwards compatible. 1274 if (document && (document->isPluginDocument() || document->isImageDocument())) 1275 return nil; 1276 1277 return kit(coreFrame->document()); 1278} 1279 1280- (DOMHTMLElement *)frameElement 1281{ 1282 Frame* coreFrame = _private->coreFrame; 1283 if (!coreFrame) 1284 return nil; 1285 return kit(coreFrame->ownerElement()); 1286} 1287 1288- (WebDataSource *)provisionalDataSource 1289{ 1290 Frame* coreFrame = _private->coreFrame; 1291 return coreFrame ? dataSource(coreFrame->loader()->provisionalDocumentLoader()) : nil; 1292} 1293 1294- (WebDataSource *)dataSource 1295{ 1296 Frame* coreFrame = _private->coreFrame; 1297 return coreFrame && coreFrame->loader()->frameHasLoaded() ? [self _dataSource] : nil; 1298} 1299 1300- (void)loadRequest:(NSURLRequest *)request 1301{ 1302 _private->coreFrame->loader()->load(request, false); 1303} 1304 1305static NSURL *createUniqueWebDataURL() 1306{ 1307 CFUUIDRef UUIDRef = CFUUIDCreate(kCFAllocatorDefault); 1308 NSString *UUIDString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, UUIDRef); 1309 CFRelease(UUIDRef); 1310 NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:@"applewebdata://%@", UUIDString]]; 1311 CFRelease(UUIDString); 1312 return URL; 1313} 1314 1315- (void)_loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)baseURL unreachableURL:(NSURL *)unreachableURL 1316{ 1317 KURL responseURL; 1318 if (!baseURL) { 1319 baseURL = blankURL(); 1320 responseURL = createUniqueWebDataURL(); 1321 } 1322 1323 ResourceRequest request([baseURL absoluteURL]); 1324 1325 // hack because Mail checks for this property to detect data / archive loads 1326 [NSURLProtocol setProperty:@"" forKey:@"WebDataRequest" inRequest:(NSMutableURLRequest *)request.nsURLRequest()]; 1327 1328 SubstituteData substituteData(WebCore::SharedBuffer::wrapNSData(data), MIMEType, encodingName, [unreachableURL absoluteURL], responseURL); 1329 1330 _private->coreFrame->loader()->load(request, substituteData, false); 1331} 1332 1333 1334- (void)loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)baseURL 1335{ 1336 if (!MIMEType) 1337 MIMEType = @"text/html"; 1338 [self _loadData:data MIMEType:MIMEType textEncodingName:encodingName baseURL:baseURL unreachableURL:nil]; 1339} 1340 1341- (void)_loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL unreachableURL:(NSURL *)unreachableURL 1342{ 1343 NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding]; 1344 [self _loadData:data MIMEType:@"text/html" textEncodingName:@"UTF-8" baseURL:baseURL unreachableURL:unreachableURL]; 1345} 1346 1347- (void)loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL 1348{ 1349 [self _loadHTMLString:string baseURL:baseURL unreachableURL:nil]; 1350} 1351 1352- (void)loadAlternateHTMLString:(NSString *)string baseURL:(NSURL *)baseURL forUnreachableURL:(NSURL *)unreachableURL 1353{ 1354 [self _loadHTMLString:string baseURL:baseURL unreachableURL:unreachableURL]; 1355} 1356 1357- (void)loadArchive:(WebArchive *)archive 1358{ 1359 if (LegacyWebArchive* coreArchive = [archive _coreLegacyWebArchive]) 1360 _private->coreFrame->loader()->loadArchive(coreArchive); 1361} 1362 1363- (void)stopLoading 1364{ 1365 if (!_private->coreFrame) 1366 return; 1367 _private->coreFrame->loader()->stopForUserCancel(); 1368} 1369 1370- (void)reload 1371{ 1372 if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_RELOAD_FROM_ORIGIN) && 1373 [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.Safari"]) 1374 _private->coreFrame->loader()->reload(GetCurrentKeyModifiers() & shiftKey); 1375 else 1376 _private->coreFrame->loader()->reload(false); 1377} 1378 1379- (void)reloadFromOrigin 1380{ 1381 _private->coreFrame->loader()->reload(true); 1382} 1383 1384- (WebFrame *)findFrameNamed:(NSString *)name 1385{ 1386 Frame* coreFrame = _private->coreFrame; 1387 if (!coreFrame) 1388 return nil; 1389 return kit(coreFrame->tree()->find(name)); 1390} 1391 1392- (WebFrame *)parentFrame 1393{ 1394 Frame* coreFrame = _private->coreFrame; 1395 if (!coreFrame) 1396 return nil; 1397 return [[kit(coreFrame->tree()->parent()) retain] autorelease]; 1398} 1399 1400- (NSArray *)childFrames 1401{ 1402 Frame* coreFrame = _private->coreFrame; 1403 if (!coreFrame) 1404 return [NSArray array]; 1405 NSMutableArray *children = [NSMutableArray arrayWithCapacity:coreFrame->tree()->childCount()]; 1406 for (Frame* child = coreFrame->tree()->firstChild(); child; child = child->tree()->nextSibling()) 1407 [children addObject:kit(child)]; 1408 return children; 1409} 1410 1411- (WebScriptObject *)windowObject 1412{ 1413 Frame* coreFrame = _private->coreFrame; 1414 if (!coreFrame) 1415 return 0; 1416 return coreFrame->script()->windowScriptObject(); 1417} 1418 1419- (JSGlobalContextRef)globalContext 1420{ 1421 Frame* coreFrame = _private->coreFrame; 1422 if (!coreFrame) 1423 return 0; 1424 return toGlobalRef(coreFrame->script()->globalObject()->globalExec()); 1425} 1426 1427@end 1428