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 _private->coreFrame->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, RenderLayer::gAlignToEdgeIfNeeded, RenderLayer::gAlignToEdgeIfNeeded); 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()->get(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.toRange().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().toRange().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.offset(), exception); 828 range->setEnd(newStart.node(), newStart.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)_replaceSelectionWithFragment:(DOMDocumentFragment *)fragment selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle 913{ 914 if (_private->coreFrame->selection()->isNone() || !fragment) 915 return; 916 917 applyCommand(ReplaceSelectionCommand::create(_private->coreFrame->document(), [fragment _documentFragment], selectReplacement, smartReplace, matchStyle)); 918 _private->coreFrame->revealSelection(RenderLayer::gAlignToEdgeIfNeeded); 919} 920 921- (void)_replaceSelectionWithNode:(DOMNode *)node selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle 922{ 923 DOMDocumentFragment *fragment = [DOMDocumentFragment _wrapDocumentFragment:_private->coreFrame->document()->createDocumentFragment().get()]; 924 [fragment appendChild:node]; 925 [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:matchStyle]; 926} 927 928- (void)_replaceSelectionWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace 929{ 930 DOMDocumentFragment *fragment = [self _documentFragmentWithMarkupString:markupString baseURLString:baseURLString]; 931 [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:NO]; 932} 933 934- (void)_replaceSelectionWithText:(NSString *)text selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace 935{ 936 [self _replaceSelectionWithFragment:kit(createFragmentFromText(_private->coreFrame->selection()->toRange().get(), text).get()) 937 selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:YES]; 938} 939 940- (void)_insertParagraphSeparatorInQuotedContent 941{ 942 if (_private->coreFrame->selection()->isNone()) 943 return; 944 945 TypingCommand::insertParagraphSeparatorInQuotedContent(_private->coreFrame->document()); 946 _private->coreFrame->revealSelection(RenderLayer::gAlignToEdgeIfNeeded); 947} 948 949- (VisiblePosition)_visiblePositionForPoint:(NSPoint)point 950{ 951 IntPoint outerPoint(point); 952 HitTestResult result = _private->coreFrame->eventHandler()->hitTestResultAtPoint(outerPoint, true); 953 Node* node = result.innerNode(); 954 if (!node) 955 return VisiblePosition(); 956 RenderObject* renderer = node->renderer(); 957 if (!renderer) 958 return VisiblePosition(); 959 VisiblePosition visiblePos = renderer->positionForCoordinates(result.localPoint().x(), result.localPoint().y()); 960 if (visiblePos.isNull()) 961 visiblePos = VisiblePosition(Position(node, 0)); 962 return visiblePos; 963} 964 965- (DOMRange *)_characterRangeAtPoint:(NSPoint)point 966{ 967 VisiblePosition position = [self _visiblePositionForPoint:point]; 968 if (position.isNull()) 969 return nil; 970 971 VisiblePosition previous = position.previous(); 972 if (previous.isNotNull()) { 973 DOMRange *previousCharacterRange = [DOMRange _wrapRange:makeRange(previous, position).get()]; 974 NSRect rect = [self _firstRectForDOMRange:previousCharacterRange]; 975 if (NSPointInRect(point, rect)) 976 return previousCharacterRange; 977 } 978 979 VisiblePosition next = position.next(); 980 if (next.isNotNull()) { 981 DOMRange *nextCharacterRange = [DOMRange _wrapRange:makeRange(position, next).get()]; 982 NSRect rect = [self _firstRectForDOMRange:nextCharacterRange]; 983 if (NSPointInRect(point, rect)) 984 return nextCharacterRange; 985 } 986 987 return nil; 988} 989 990- (DOMCSSStyleDeclaration *)_typingStyle 991{ 992 if (!_private->coreFrame || !_private->coreFrame->typingStyle()) 993 return nil; 994 return [DOMCSSStyleDeclaration _wrapCSSStyleDeclaration:_private->coreFrame->typingStyle()->copy().get()]; 995} 996 997- (void)_setTypingStyle:(DOMCSSStyleDeclaration *)style withUndoAction:(EditAction)undoAction 998{ 999 if (!_private->coreFrame) 1000 return; 1001 _private->coreFrame->computeAndSetTypingStyle([style _CSSStyleDeclaration], undoAction); 1002} 1003 1004- (void)_dragSourceMovedTo:(NSPoint)windowLoc 1005{ 1006 if (!_private->coreFrame) 1007 return; 1008 FrameView* view = _private->coreFrame->view(); 1009 if (!view) 1010 return; 1011 // FIXME: These are fake modifier keys here, but they should be real ones instead. 1012 PlatformMouseEvent event(IntPoint(windowLoc), globalPoint(windowLoc, [view->platformWidget() window]), 1013 LeftButton, MouseEventMoved, 0, false, false, false, false, currentTime()); 1014 _private->coreFrame->eventHandler()->dragSourceMovedTo(event); 1015} 1016 1017- (void)_dragSourceEndedAt:(NSPoint)windowLoc operation:(NSDragOperation)operation 1018{ 1019 if (!_private->coreFrame) 1020 return; 1021 FrameView* view = _private->coreFrame->view(); 1022 if (!view) 1023 return; 1024 // FIXME: These are fake modifier keys here, but they should be real ones instead. 1025 PlatformMouseEvent event(IntPoint(windowLoc), globalPoint(windowLoc, [view->platformWidget() window]), 1026 LeftButton, MouseEventMoved, 0, false, false, false, false, currentTime()); 1027 _private->coreFrame->eventHandler()->dragSourceEndedAt(event, (DragOperation)operation); 1028} 1029 1030- (BOOL)_canProvideDocumentSource 1031{ 1032 Frame* frame = _private->coreFrame; 1033 String mimeType = frame->loader()->responseMIMEType(); 1034 PluginData* pluginData = frame->page() ? frame->page()->pluginData() : 0; 1035 1036 if (WebCore::DOMImplementation::isTextMIMEType(mimeType) || 1037 Image::supportsType(mimeType) || 1038 (pluginData && pluginData->supportsMimeType(mimeType))) 1039 return NO; 1040 1041 return YES; 1042} 1043 1044- (BOOL)_canSaveAsWebArchive 1045{ 1046 // Currently, all documents that we can view source for 1047 // (HTML and XML documents) can also be saved as web archives 1048 return [self _canProvideDocumentSource]; 1049} 1050 1051- (void)_receivedData:(NSData *)data textEncodingName:(NSString *)textEncodingName 1052{ 1053 // Set the encoding. This only needs to be done once, but it's harmless to do it again later. 1054 String encoding = _private->coreFrame->loader()->documentLoader()->overrideEncoding(); 1055 bool userChosen = !encoding.isNull(); 1056 if (encoding.isNull()) 1057 encoding = textEncodingName; 1058 _private->coreFrame->loader()->setEncoding(encoding, userChosen); 1059 [self _addData:data]; 1060} 1061 1062@end 1063 1064@implementation WebFrame (WebPrivate) 1065 1066// FIXME: This exists only as a convenience for Safari, consider moving there. 1067- (BOOL)_isDescendantOfFrame:(WebFrame *)ancestor 1068{ 1069 Frame* coreFrame = _private->coreFrame; 1070 return coreFrame && coreFrame->tree()->isDescendantOf(core(ancestor)); 1071} 1072 1073- (void)_setShouldCreateRenderers:(BOOL)shouldCreateRenderers 1074{ 1075 _private->shouldCreateRenderers = shouldCreateRenderers; 1076} 1077 1078- (NSColor *)_bodyBackgroundColor 1079{ 1080 Document* document = _private->coreFrame->document(); 1081 if (!document) 1082 return nil; 1083 HTMLElement* body = document->body(); 1084 if (!body) 1085 return nil; 1086 RenderObject* bodyRenderer = body->renderer(); 1087 if (!bodyRenderer) 1088 return nil; 1089 Color color = bodyRenderer->style()->backgroundColor(); 1090 if (!color.isValid()) 1091 return nil; 1092 return nsColor(color); 1093} 1094 1095- (BOOL)_isFrameSet 1096{ 1097 return _private->coreFrame->isFrameSet(); 1098} 1099 1100- (BOOL)_firstLayoutDone 1101{ 1102 return _private->coreFrame->loader()->firstLayoutDone(); 1103} 1104 1105- (WebFrameLoadType)_loadType 1106{ 1107 return (WebFrameLoadType)_private->coreFrame->loader()->loadType(); 1108} 1109 1110- (NSRange)_selectedNSRange 1111{ 1112 return [self _convertToNSRange:_private->coreFrame->selection()->toRange().get()]; 1113} 1114 1115- (void)_selectNSRange:(NSRange)range 1116{ 1117 RefPtr<Range> domRange = [self _convertToDOMRange:range]; 1118 if (domRange) 1119 _private->coreFrame->selection()->setSelection(Selection(domRange.get(), SEL_DEFAULT_AFFINITY)); 1120} 1121 1122- (BOOL)_isDisplayingStandaloneImage 1123{ 1124 Document* document = _private->coreFrame->document(); 1125 return document && document->isImageDocument(); 1126} 1127 1128- (unsigned)_pendingFrameUnloadEventCount 1129{ 1130 return _private->coreFrame->eventHandler()->pendingFrameUnloadEventCount(); 1131} 1132 1133- (WebIconFetcher *)fetchApplicationIcon:(id)target 1134 selector:(SEL)selector 1135{ 1136 return [WebIconFetcher _fetchApplicationIconForFrame:self 1137 target:target 1138 selector:selector]; 1139} 1140 1141- (void)_setIsDisconnected:(bool)isDisconnected 1142{ 1143 _private->coreFrame->setIsDisconnected(isDisconnected); 1144} 1145 1146- (void)_setExcludeFromTextSearch:(bool)exclude 1147{ 1148 _private->coreFrame->setExcludeFromTextSearch(exclude); 1149} 1150 1151#if ENABLE(NETSCAPE_PLUGIN_API) 1152- (void)_recursive_resumeNullEventsForAllNetscapePlugins 1153{ 1154 Frame* coreFrame = core(self); 1155 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) { 1156 NSView <WebDocumentView> *documentView = [[kit(frame) frameView] documentView]; 1157 if ([documentView isKindOfClass:[WebHTMLView class]]) 1158 [(WebHTMLView *)documentView _resumeNullEventsForAllNetscapePlugins]; 1159 } 1160} 1161 1162- (void)_recursive_pauseNullEventsForAllNetscapePlugins 1163{ 1164 Frame* coreFrame = core(self); 1165 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) { 1166 NSView <WebDocumentView> *documentView = [[kit(frame) frameView] documentView]; 1167 if ([documentView isKindOfClass:[WebHTMLView class]]) 1168 [(WebHTMLView *)documentView _pauseNullEventsForAllNetscapePlugins]; 1169 } 1170} 1171#endif 1172 1173- (BOOL)_pauseAnimation:(NSString*)name onNode:(DOMNode *)node atTime:(NSTimeInterval)time 1174{ 1175 Frame* frame = core(self); 1176 if (!frame) 1177 return false; 1178 1179 AnimationController* controller = frame->animation(); 1180 if (!controller) 1181 return false; 1182 1183 Node* coreNode = [node _node]; 1184 if (!coreNode || !coreNode->renderer()) 1185 return false; 1186 1187 return controller->pauseAnimationAtTime(coreNode->renderer(), name, time); 1188} 1189 1190- (BOOL)_pauseTransitionOfProperty:(NSString*)name onNode:(DOMNode*)node atTime:(NSTimeInterval)time 1191{ 1192 Frame* frame = core(self); 1193 if (!frame) 1194 return false; 1195 1196 AnimationController* controller = frame->animation(); 1197 if (!controller) 1198 return false; 1199 1200 Node* coreNode = [node _node]; 1201 if (!coreNode || !coreNode->renderer()) 1202 return false; 1203 1204 return controller->pauseTransitionAtTime(coreNode->renderer(), name, time); 1205} 1206 1207- (unsigned) _numberOfActiveAnimations 1208{ 1209 Frame* frame = core(self); 1210 if (!frame) 1211 return false; 1212 1213 AnimationController* controller = frame->animation(); 1214 if (!controller) 1215 return false; 1216 1217 return controller->numberOfActiveAnimations(); 1218} 1219 1220@end 1221 1222@implementation WebFrame 1223 1224- (id)init 1225{ 1226 return nil; 1227} 1228 1229// Should be deprecated. 1230- (id)initWithName:(NSString *)name webFrameView:(WebFrameView *)view webView:(WebView *)webView 1231{ 1232 return nil; 1233} 1234 1235- (void)dealloc 1236{ 1237 [_private release]; 1238 --WebFrameCount; 1239 [super dealloc]; 1240} 1241 1242- (void)finalize 1243{ 1244 --WebFrameCount; 1245 [super finalize]; 1246} 1247 1248- (NSString *)name 1249{ 1250 Frame* coreFrame = _private->coreFrame; 1251 if (!coreFrame) 1252 return nil; 1253 return coreFrame->tree()->name(); 1254} 1255 1256- (WebFrameView *)frameView 1257{ 1258 return _private->webFrameView; 1259} 1260 1261- (WebView *)webView 1262{ 1263 return getWebView(self); 1264} 1265 1266- (DOMDocument *)DOMDocument 1267{ 1268 Frame* coreFrame = _private->coreFrame; 1269 if (!coreFrame) 1270 return nil; 1271 1272 // FIXME: <rdar://problem/5145841> When loading a custom view/representation 1273 // into a web frame, the old document can still be around. This makes sure that 1274 // we'll return nil in those cases. 1275 if (![[self _dataSource] _isDocumentHTML]) 1276 return nil; 1277 1278 Document* document = coreFrame->document(); 1279 1280 // According to the documentation, we should return nil if the frame doesn't have a document. 1281 // While full-frame images and plugins do have an underlying HTML document, we return nil here to be 1282 // backwards compatible. 1283 if (document && (document->isPluginDocument() || document->isImageDocument())) 1284 return nil; 1285 1286 return kit(coreFrame->document()); 1287} 1288 1289- (DOMHTMLElement *)frameElement 1290{ 1291 Frame* coreFrame = _private->coreFrame; 1292 if (!coreFrame) 1293 return nil; 1294 return kit(coreFrame->ownerElement()); 1295} 1296 1297- (WebDataSource *)provisionalDataSource 1298{ 1299 Frame* coreFrame = _private->coreFrame; 1300 return coreFrame ? dataSource(coreFrame->loader()->provisionalDocumentLoader()) : nil; 1301} 1302 1303- (WebDataSource *)dataSource 1304{ 1305 Frame* coreFrame = _private->coreFrame; 1306 return coreFrame && coreFrame->loader()->frameHasLoaded() ? [self _dataSource] : nil; 1307} 1308 1309- (void)loadRequest:(NSURLRequest *)request 1310{ 1311 _private->coreFrame->loader()->load(request, false); 1312} 1313 1314static NSURL *createUniqueWebDataURL() 1315{ 1316 CFUUIDRef UUIDRef = CFUUIDCreate(kCFAllocatorDefault); 1317 NSString *UUIDString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, UUIDRef); 1318 CFRelease(UUIDRef); 1319 NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:@"applewebdata://%@", UUIDString]]; 1320 CFRelease(UUIDString); 1321 return URL; 1322} 1323 1324- (void)_loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)baseURL unreachableURL:(NSURL *)unreachableURL 1325{ 1326 KURL responseURL; 1327 if (!baseURL) { 1328 baseURL = blankURL(); 1329 responseURL = createUniqueWebDataURL(); 1330 } 1331 1332 ResourceRequest request([baseURL absoluteURL]); 1333 1334 // hack because Mail checks for this property to detect data / archive loads 1335 [NSURLProtocol setProperty:@"" forKey:@"WebDataRequest" inRequest:(NSMutableURLRequest *)request.nsURLRequest()]; 1336 1337 SubstituteData substituteData(WebCore::SharedBuffer::wrapNSData(data), MIMEType, encodingName, [unreachableURL absoluteURL], responseURL); 1338 1339 _private->coreFrame->loader()->load(request, substituteData, false); 1340} 1341 1342 1343- (void)loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)baseURL 1344{ 1345 if (!MIMEType) 1346 MIMEType = @"text/html"; 1347 [self _loadData:data MIMEType:MIMEType textEncodingName:encodingName baseURL:baseURL unreachableURL:nil]; 1348} 1349 1350- (void)_loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL unreachableURL:(NSURL *)unreachableURL 1351{ 1352 NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding]; 1353 [self _loadData:data MIMEType:@"text/html" textEncodingName:@"UTF-8" baseURL:baseURL unreachableURL:unreachableURL]; 1354} 1355 1356- (void)loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL 1357{ 1358 [self _loadHTMLString:string baseURL:baseURL unreachableURL:nil]; 1359} 1360 1361- (void)loadAlternateHTMLString:(NSString *)string baseURL:(NSURL *)baseURL forUnreachableURL:(NSURL *)unreachableURL 1362{ 1363 [self _loadHTMLString:string baseURL:baseURL unreachableURL:unreachableURL]; 1364} 1365 1366- (void)loadArchive:(WebArchive *)archive 1367{ 1368 if (LegacyWebArchive* coreArchive = [archive _coreLegacyWebArchive]) 1369 _private->coreFrame->loader()->loadArchive(coreArchive); 1370} 1371 1372- (void)stopLoading 1373{ 1374 if (!_private->coreFrame) 1375 return; 1376 _private->coreFrame->loader()->stopForUserCancel(); 1377} 1378 1379- (void)reload 1380{ 1381 if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_RELOAD_FROM_ORIGIN) && 1382 [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.Safari"]) 1383 _private->coreFrame->loader()->reload(GetCurrentKeyModifiers() & shiftKey); 1384 else 1385 _private->coreFrame->loader()->reload(false); 1386} 1387 1388- (void)reloadFromOrigin 1389{ 1390 _private->coreFrame->loader()->reload(true); 1391} 1392 1393- (WebFrame *)findFrameNamed:(NSString *)name 1394{ 1395 Frame* coreFrame = _private->coreFrame; 1396 if (!coreFrame) 1397 return nil; 1398 return kit(coreFrame->tree()->find(name)); 1399} 1400 1401- (WebFrame *)parentFrame 1402{ 1403 Frame* coreFrame = _private->coreFrame; 1404 if (!coreFrame) 1405 return nil; 1406 return [[kit(coreFrame->tree()->parent()) retain] autorelease]; 1407} 1408 1409- (NSArray *)childFrames 1410{ 1411 Frame* coreFrame = _private->coreFrame; 1412 if (!coreFrame) 1413 return [NSArray array]; 1414 NSMutableArray *children = [NSMutableArray arrayWithCapacity:coreFrame->tree()->childCount()]; 1415 for (Frame* child = coreFrame->tree()->firstChild(); child; child = child->tree()->nextSibling()) 1416 [children addObject:kit(child)]; 1417 return children; 1418} 1419 1420- (WebScriptObject *)windowObject 1421{ 1422 Frame* coreFrame = _private->coreFrame; 1423 if (!coreFrame) 1424 return 0; 1425 return coreFrame->script()->windowScriptObject(); 1426} 1427 1428- (JSGlobalContextRef)globalContext 1429{ 1430 Frame* coreFrame = _private->coreFrame; 1431 if (!coreFrame) 1432 return 0; 1433 return toGlobalRef(coreFrame->script()->globalObject()->globalExec()); 1434} 1435 1436@end 1437