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