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