Reviewed by Tim.
[WebKit-https.git] / WebKit / WebView / WebFrame.mm
1 /*
2  * Copyright (C) 2005, 2006 Apple Computer, 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 "DOMDocumentInternal.h"
33 #import "DOMElementInternal.h"
34 #import "DOMHTMLElementInternal.h"
35 #import "DOMNodeInternal.h"
36 #import "DOMRangeInternal.h"
37 #import "WebBackForwardList.h"
38 #import "WebChromeClient.h"
39 #import "WebDataSourceInternal.h"
40 #import "WebDocumentInternal.h"
41 #import "WebDocumentLoaderMac.h"
42 #import "WebFrameBridge.h"
43 #import "WebFrameLoadDelegate.h"
44 #import "WebFrameLoaderClient.h"
45 #import "WebFrameViewInternal.h"
46 #import "WebHTMLViewInternal.h"
47 #import "WebHistoryItem.h"
48 #import "WebHistoryItemInternal.h"
49 #import "WebHistoryItemPrivate.h"
50 #import "WebKitLogging.h"
51 #import "WebKitStatisticsPrivate.h"
52 #import "WebNSURLExtras.h"
53 #import "WebNSURLRequestExtras.h"
54 #import "WebNetscapePluginEmbeddedView.h"
55 #import "WebNullPluginView.h"
56 #import "WebPlugin.h"
57 #import "WebPluginController.h"
58 #import "WebPreferencesPrivate.h"
59 #import "WebScriptDebugDelegatePrivate.h"
60 #import "WebViewInternal.h"
61 #import <WebCore/Chrome.h>
62 #import <WebCore/ColorMac.h>
63 #import <WebCore/Document.h>
64 #import <WebCore/Event.h>
65 #import <WebCore/FrameLoader.h>
66 #import <WebCore/Frame.h>
67 #import <WebCore/FrameTree.h>
68 #import <WebCore/HistoryItem.h>
69 #import <WebCore/HTMLFormElement.h>
70 #import <WebCore/HTMLFrameOwnerElement.h>
71 #import <WebCore/Page.h>
72 #import <WebCore/SelectionController.h>
73 #import <WebCore/SharedBuffer.h>
74 #import <WebCore/FormState.h>
75 #import <WebCore/ResourceRequest.h>
76 #import <WebCore/kjs_binding.h>
77 #import <WebCore/kjs_proxy.h>
78 #import <WebKit/DOMDocument.h>
79 #import <WebKit/DOMElement.h>
80 #import <WebKit/DOMHTMLElement.h>
81 #import <WebKit/DOMNode.h>
82 #import <WebKit/DOMRange.h>
83
84 using namespace WebCore;
85
86 /*
87 Here is the current behavior matrix for four types of navigations:
88
89 Standard Nav:
90
91  Restore form state:   YES
92  Restore scroll and focus state:  YES
93  Cache policy: NSURLRequestUseProtocolCachePolicy
94  Add to back/forward list: YES
95  
96 Back/Forward:
97
98  Restore form state:   YES
99  Restore scroll and focus state:  YES
100  Cache policy: NSURLRequestReturnCacheDataElseLoad
101  Add to back/forward list: NO
102
103 Reload (meaning only the reload button):
104
105  Restore form state:   NO
106  Restore scroll and focus state:  YES
107  Cache policy: NSURLRequestReloadIgnoringCacheData
108  Add to back/forward list: NO
109
110 Repeat load of the same URL (by any other means of navigation other than the reload button, including hitting return in the location field):
111
112  Restore form state:   NO
113  Restore scroll and focus state:  NO, reset to initial conditions
114  Cache policy: NSURLRequestReloadIgnoringCacheData
115  Add to back/forward list: NO
116 */
117
118 using namespace WebCore;
119
120 NSString *WebPageCacheEntryDateKey = @"WebPageCacheEntryDateKey";
121 NSString *WebPageCacheDataSourceKey = @"WebPageCacheDataSourceKey";
122 NSString *WebPageCacheDocumentViewKey = @"WebPageCacheDocumentViewKey";
123
124 @interface WebFrame (ForwardDecls)
125 - (void)_loadHTMLString:(NSString *)string baseURL:(NSURL *)URL unreachableURL:(NSURL *)unreachableURL;
126 - (WebHistoryItem *)_createItem:(BOOL)useOriginal;
127 - (WebHistoryItem *)_createItemTreeWithTargetFrame:(WebFrame *)targetFrame clippedAtTarget:(BOOL)doClip;
128 @end
129
130 @interface NSView (WebFramePluginHosting)
131 - (void)setWebFrame:(WebFrame *)webFrame;
132 @end
133
134 @implementation WebFramePrivate
135
136 - (void)dealloc
137 {
138     [webFrameView release];
139     
140     [scriptDebugger release];
141
142     [super dealloc];
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 HTMLElement* core(DOMHTMLElement *element)
200 {
201     return [element _HTMLElement];
202 }
203
204 DOMHTMLElement *kit(HTMLElement *element)
205 {
206     return [DOMHTMLElement _wrapHTMLElement:element];
207 }
208
209 Range* core(DOMRange *range)
210 {
211     return [range _range];
212 }
213
214 DOMRange *kit(Range* range)
215 {
216     return [DOMRange _wrapRange:range];
217 }
218
219 WebCore::EditableLinkBehavior core(WebKitEditableLinkBehavior editableLinkBehavior)
220 {
221     return static_cast<WebCore::EditableLinkBehavior>(editableLinkBehavior);
222 }
223
224 WebKitEditableLinkBehavior kit(WebCore::EditableLinkBehavior editableLinkBehavior)
225 {
226     return static_cast<WebKitEditableLinkBehavior>(editableLinkBehavior);
227 }
228
229 @implementation WebFrame (WebInternal)
230
231
232 static inline WebFrame *frame(WebCoreFrameBridge *bridge)
233 {
234     return ((WebFrameBridge *)bridge)->_frame;
235 }
236
237 Frame* core(WebFrame *frame)
238 {
239     if (!frame)
240         return 0;
241     
242     if (!frame->_private->bridge)
243         return 0;
244
245     return frame->_private->bridge->m_frame;
246 }
247
248 WebFrame *kit(Frame* frame)
249 {
250     return frame ? ((WebFrameBridge *)frame->bridge())->_frame : nil;
251 }
252
253 Page* core(WebView *webView)
254 {
255     return [webView page];
256 }
257
258 WebView *kit(Page* page)
259 {
260     return page ? static_cast<WebChromeClient*>(page->chrome()->client())->webView() : nil;
261 }
262
263 WebView *getWebView(WebFrame *webFrame)
264 {
265     Frame* coreFrame = core(webFrame);
266     if (!coreFrame)
267         return nil;
268     return kit(coreFrame->page());
269 }
270
271 /*
272     In the case of saving state about a page with frames, we store a tree of items that mirrors the frame tree.  
273     The item that was the target of the user's navigation is designated as the "targetItem".  
274     When this method is called with doClip=YES we're able to create the whole tree except for the target's children, 
275     which will be loaded in the future.  That part of the tree will be filled out as the child loads are committed.
276 */
277
278 + (CFAbsoluteTime)_timeOfLastCompletedLoad
279 {
280     return FrameLoader::timeOfLastCompletedLoad() - kCFAbsoluteTimeIntervalSince1970;
281 }
282
283 - (WebFrameBridge *)_bridge
284 {
285     return _private->bridge;
286 }
287
288 - (void)_loadURL:(NSURL *)URL referrer:(NSString *)referrer intoChild:(WebFrame *)childFrame
289 {
290     ASSERT(childFrame);
291     HistoryItem* parentItem = core(self)->loader()->currentHistoryItem();
292     FrameLoadType loadType = [self _frameLoader]->loadType();
293     FrameLoadType childLoadType = FrameLoadTypeRedirectWithLockedHistory;
294
295     // If we're moving in the backforward list, we might want to replace the content
296     // of this child frame with whatever was there at that point.
297     // Reload will maintain the frame contents, LoadSame will not.
298     if (parentItem && parentItem->children().size() &&
299         (isBackForwardLoadType(loadType)
300          || loadType == FrameLoadTypeReload
301          || loadType == FrameLoadTypeReloadAllowingStaleData))
302     {
303         HistoryItem* childItem = parentItem->childItemWithName([childFrame name]);
304         if (childItem) {
305             // Use the original URL to ensure we get all the side-effects, such as
306             // onLoad handlers, of any redirects that happened. An example of where
307             // this is needed is Radar 3213556.
308             URL = [NSURL _web_URLWithDataAsString:childItem->originalURLString()];
309             // These behaviors implied by these loadTypes should apply to the child frames
310             childLoadType = loadType;
311
312             if (isBackForwardLoadType(loadType))
313                 // For back/forward, remember this item so we can traverse any child items as child frames load
314                 core(childFrame)->loader()->setProvisionalHistoryItem(childItem);
315             else
316                 // For reload, just reinstall the current item, since a new child frame was created but we won't be creating a new BF item
317                 core(childFrame)->loader()->setCurrentHistoryItem(childItem);
318         }
319     }
320
321     WebArchive *archive = [[self _dataSource] _popSubframeArchiveWithName:[childFrame name]];
322     if (archive)
323         [childFrame loadArchive:archive];
324     else
325         [childFrame _frameLoader]->load([URL absoluteURL], referrer, childLoadType,
326                                         String(), 0, 0);
327 }
328
329
330 - (void)_viewWillMoveToHostWindow:(NSWindow *)hostWindow
331 {
332     Frame* coreFrame = core(self);
333     for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
334         [[[kit(frame) frameView] documentView] viewWillMoveToHostWindow:hostWindow];
335 }
336
337 - (void)_viewDidMoveToHostWindow
338 {
339     Frame* coreFrame = core(self);
340     for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
341         [[[kit(frame) frameView] documentView] viewDidMoveToHostWindow];
342 }
343
344 - (void)_addChild:(WebFrame *)child
345 {
346     core(self)->tree()->appendChild(adoptRef(core(child)));
347     if ([child _dataSource])
348         [[child _dataSource] _documentLoader]->setOverrideEncoding([[self _dataSource] _documentLoader]->overrideEncoding());  
349 }
350
351 - (int)_numPendingOrLoadingRequests:(BOOL)recurse
352 {
353     return core(self)->loader()->numPendingOrLoadingRequests(recurse);
354 }
355
356 - (void)_reloadForPluginChanges
357 {
358     Frame* coreFrame = core(self);
359     for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
360         NSView <WebDocumentView> *documentView = [[kit(frame) frameView] documentView];
361         if (([documentView isKindOfClass:[WebHTMLView class]] && coreFrame->loader()->containsPlugins()))
362             [kit(frame) reload];
363     }
364 }
365
366 - (void)_attachScriptDebugger
367 {
368     if (!_private->scriptDebugger && core(self)->scriptProxy()->haveInterpreter())
369         _private->scriptDebugger = [[WebScriptDebugger alloc] initWithWebFrame:self];
370 }
371
372 - (void)_detachScriptDebugger
373 {
374     if (_private->scriptDebugger) {
375         id old = _private->scriptDebugger;
376         _private->scriptDebugger = nil;
377         [old release];
378     }
379 }
380
381 - (id)_initWithWebFrameView:(WebFrameView *)fv webView:(WebView *)v bridge:(WebFrameBridge *)bridge
382 {
383     self = [super init];
384     if (!self)
385         return nil;
386
387     _private = [[WebFramePrivate alloc] init];
388     _private->bridge = bridge;
389
390     if (fv) {
391         [_private setWebFrameView:fv];
392         [fv _setWebFrame:self];
393     }
394
395     ++WebFrameCount;
396
397     return self;
398 }
399
400 - (NSArray *)_documentViews
401 {
402     NSMutableArray *result = [NSMutableArray array];
403     Frame* coreFrame = core(self);
404     for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
405         id docView = [[kit(frame) frameView] documentView];
406         if (docView)
407             [result addObject:docView];
408     }
409     return result;
410 }
411
412 - (void)_updateBackground
413 {
414     BOOL drawsBackground = [getWebView(self) drawsBackground];
415     NSColor *backgroundColor = [getWebView(self) backgroundColor];
416
417     Frame* coreFrame = core(self);
418     for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
419         WebFrameBridge *bridge = (WebFrameBridge *)frame->bridge();
420         WebFrame *webFrame = [bridge webFrame];
421         // Never call setDrawsBackground:YES here on the scroll view or the background color will
422         // flash between pages loads. setDrawsBackground:YES will be called in _frameLoadCompleted.
423         if (!drawsBackground)
424             [[[webFrame frameView] _scrollView] setDrawsBackground:NO];
425         [[[webFrame frameView] _scrollView] setBackgroundColor:backgroundColor];
426         id documentView = [[webFrame frameView] documentView];
427         if ([documentView respondsToSelector:@selector(setDrawsBackground:)])
428             [documentView setDrawsBackground:drawsBackground];
429         if ([documentView respondsToSelector:@selector(setBackgroundColor:)])
430             [documentView setBackgroundColor:backgroundColor];
431         [bridge setDrawsBackground:drawsBackground];
432         [bridge setBaseBackgroundColor:backgroundColor];
433     }
434 }
435
436 - (void)_setInternalLoadDelegate:(id)internalLoadDelegate
437 {
438     _private->internalLoadDelegate = internalLoadDelegate;
439 }
440
441 - (id)_internalLoadDelegate
442 {
443     return _private->internalLoadDelegate;
444 }
445
446 #ifndef BUILDING_ON_TIGER
447 - (void)_unmarkAllBadGrammar
448 {
449     Frame* coreFrame = core(self);
450     for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
451         Document *doc = frame->document();
452         if (!doc)
453             return;
454
455         doc->removeMarkers(DocumentMarker::Grammar);
456     }
457 }
458 #endif
459
460 - (void)_unmarkAllMisspellings
461 {
462     Frame* coreFrame = core(self);
463     for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
464         Document *doc = frame->document();
465         if (!doc)
466             return;
467
468         doc->removeMarkers(DocumentMarker::Spelling);
469     }
470 }
471
472 - (BOOL)_hasSelection
473 {
474     id documentView = [_private->webFrameView documentView];    
475
476     // optimization for common case to avoid creating potentially large selection string
477     if ([documentView isKindOfClass:[WebHTMLView class]])
478         if (Frame* coreFrame = core(self))
479             return coreFrame->selectionController()->isRange();
480
481     if ([documentView conformsToProtocol:@protocol(WebDocumentText)])
482         return [[documentView selectedString] length] > 0;
483     
484     return NO;
485 }
486
487 - (void)_clearSelection
488 {
489     id documentView = [_private->webFrameView documentView];    
490     if ([documentView conformsToProtocol:@protocol(WebDocumentText)])
491         [documentView deselectAll];
492 }
493
494 #if !ASSERT_DISABLED
495 - (BOOL)_atMostOneFrameHasSelection
496 {
497     // FIXME: 4186050 is one known case that makes this debug check fail.
498     BOOL found = NO;
499     Frame* coreFrame = core(self);
500     for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
501         if ([kit(frame) _hasSelection]) {
502             if (found)
503                 return NO;
504             found = YES;
505         }
506     return YES;
507 }
508 #endif
509
510 - (WebFrame *)_findFrameWithSelection
511 {
512     Frame* coreFrame = core(self);
513     for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
514         if ([kit(frame) _hasSelection])
515             return kit(frame);
516     return nil;
517 }
518
519 - (void)_clearSelectionInOtherFrames
520 {
521     // We rely on WebDocumentSelection protocol implementors to call this method when they become first 
522     // responder. It would be nicer to just notice first responder changes here instead, but there's no 
523     // notification sent when the first responder changes in general (Radar 2573089).
524     WebFrame *frameWithSelection = [[getWebView(self) mainFrame] _findFrameWithSelection];
525     if (frameWithSelection != self)
526         [frameWithSelection _clearSelection];
527
528     // While we're in the general area of selection and frames, check that there is only one now.
529     ASSERT([[getWebView(self) mainFrame] _atMostOneFrameHasSelection]);
530 }
531
532 - (BOOL)_isMainFrame
533 {
534    Frame* coreFrame = core(self);
535    if (!coreFrame)
536        return NO;
537    return coreFrame == coreFrame->page()->mainFrame() ;
538 }
539
540 - (FrameLoader*)_frameLoader
541 {
542     Frame* frame = core(self);
543     return frame ? frame->loader() : 0;
544 }
545
546 static inline WebDataSource *dataSource(DocumentLoader* loader)
547 {
548     return loader ? static_cast<WebDocumentLoaderMac*>(loader)->dataSource() : nil;
549 }
550
551 - (WebDataSource *)_dataSourceForDocumentLoader:(DocumentLoader*)loader
552 {
553     return dataSource(loader);
554 }
555
556 - (void)_addDocumentLoader:(DocumentLoader*)loader toUnarchiveState:(WebArchive *)archive
557 {
558     [dataSource(loader) _addToUnarchiveState:archive];
559 }
560
561 - (WebDataSource *)_dataSource
562 {
563     FrameLoader* frameLoader = [self _frameLoader];
564
565     if (!frameLoader)
566         return nil;
567
568     return dataSource(frameLoader->documentLoader());
569 }
570
571 @end
572
573 @implementation WebFrame (WebPrivate)
574
575 // FIXME: Yhis exists only as a convenience for Safari, consider moving there.
576 - (BOOL)_isDescendantOfFrame:(WebFrame *)ancestor
577 {
578     Frame* coreFrame = core(self);
579     return coreFrame && coreFrame->tree()->isDescendantOf(core(ancestor));
580 }
581
582 - (void)_setShouldCreateRenderers:(BOOL)frame
583 {
584     [_private->bridge setShouldCreateRenderers:frame];
585 }
586
587 - (NSColor *)_bodyBackgroundColor
588 {
589     Document* document = core(self)->document();
590     if (!document)
591         return nil;
592     HTMLElement* body = document->body();
593     if (!body)
594         return nil;
595     RenderObject* bodyRenderer = body->renderer();
596     if (!bodyRenderer)
597         return nil;
598     Color color = bodyRenderer->style()->backgroundColor();
599     if (!color.isValid())
600         return nil;
601     return nsColor(color);
602 }
603
604 - (BOOL)_isFrameSet
605 {
606     return core(self)->isFrameSet();
607 }
608
609 - (BOOL)_firstLayoutDone
610 {
611     return [self _frameLoader]->firstLayoutDone();
612 }
613
614 - (WebFrameLoadType)_loadType
615 {
616     return (WebFrameLoadType)[self _frameLoader]->loadType();
617 }
618
619 #ifndef __LP64__
620 - (void)_recursive_resumeNullEventsForAllNetscapePlugins
621 {
622     Frame* coreFrame = core(self);
623     for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
624         NSView <WebDocumentView> *documentView = [[kit(frame) frameView] documentView];
625         if ([documentView isKindOfClass:[WebHTMLView class]])
626             [(WebHTMLView *)documentView _resumeNullEventsForAllNetscapePlugins];
627     }
628 }
629 #endif
630
631 #ifndef __LP64__
632 - (void)_recursive_pauseNullEventsForAllNetscapePlugins
633 {
634     Frame* coreFrame = core(self);
635     for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
636         NSView <WebDocumentView> *documentView = [[kit(frame) frameView] documentView];
637         if ([documentView isKindOfClass:[WebHTMLView class]])
638             [(WebHTMLView *)documentView _pauseNullEventsForAllNetscapePlugins];
639     }
640 }
641 #endif
642
643 - (NSRange)_selectedNSRange
644 {
645     return [_private->bridge selectedNSRange];
646 }
647
648 - (void)_selectNSRange:(NSRange)range
649 {
650     [_private->bridge selectNSRange:range];
651 }
652
653 - (BOOL)_isDisplayingStandaloneImage
654 {
655     Document* document = core(self)->document();
656     return document && document->isImageDocument();
657 }
658
659 @end
660
661 @implementation WebFrame
662
663 - (id)init
664 {
665     return nil;
666 }
667
668 // Should be deprecated.
669 - (id)initWithName:(NSString *)name webFrameView:(WebFrameView *)view webView:(WebView *)webView
670 {
671     return nil;
672 }
673
674 - (void)dealloc
675 {
676     ASSERT(_private->bridge == nil);
677     [_private release];
678     --WebFrameCount;
679     [super dealloc];
680 }
681
682 - (void)finalize
683 {
684     ASSERT(_private->bridge == nil);
685     --WebFrameCount;
686     [super finalize];
687 }
688
689 - (NSString *)name
690 {
691     Frame* coreFrame = core(self);
692     if (!coreFrame)
693         return nil;
694     return coreFrame->tree()->name();
695 }
696
697 - (WebFrameView *)frameView
698 {
699     return _private->webFrameView;
700 }
701
702 - (WebView *)webView
703 {
704     return getWebView(self);
705 }
706
707 - (DOMDocument *)DOMDocument
708 {
709     Frame* coreFrame = core(self);
710     if (!coreFrame)
711         return nil;
712     
713     // FIXME: <rdar://problem/5145841> When loading a custom view/representation 
714     // into a web frame, the old document can still be around. This makes sure that
715     // we'll return nil in those cases.
716     if (![[self _dataSource] _isDocumentHTML]) 
717         return nil; 
718
719     Document* document = coreFrame->document();
720     
721     // According to the documentation, we should return nil if the frame doesn't have a document.
722     // While full-frame images and plugins do have an underlying HTML document, we return nil here to be
723     // backwards compatible.
724     if (document && (document->isPluginDocument() || document->isImageDocument()))
725         return nil;
726     
727     return kit(coreFrame->document());
728 }
729
730 - (DOMHTMLElement *)frameElement
731 {
732     Frame* coreFrame = core(self);
733     if (!coreFrame)
734         return nil;
735     return kit(coreFrame->ownerElement());
736 }
737
738 - (WebDataSource *)provisionalDataSource
739 {
740     FrameLoader* frameLoader = [self _frameLoader];
741     return frameLoader ? dataSource(frameLoader->provisionalDocumentLoader()) : nil;
742 }
743
744 - (WebDataSource *)dataSource
745 {
746     FrameLoader* loader = [self _frameLoader];
747     if (!loader || !loader->frameHasLoaded())
748         return nil;
749
750     return [self _dataSource];
751 }
752
753 - (void)loadRequest:(NSURLRequest *)request
754 {
755     [self _frameLoader]->load(request);
756 }
757
758 static NSURL *createUniqueWebDataURL()
759 {
760     CFUUIDRef UUIDRef = CFUUIDCreate(kCFAllocatorDefault);
761     NSString *UUIDString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, UUIDRef);
762     CFRelease(UUIDRef);
763     NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:@"applewebdata://%@", UUIDString]];
764     CFRelease(UUIDString);
765     return URL;
766 }
767
768 - (void)_loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)URL unreachableURL:(NSURL *)unreachableURL
769 {
770     KURL responseURL;
771     if (!URL) {
772         URL = [NSURL URLWithString:@"about:blank"];
773         responseURL = createUniqueWebDataURL();
774     }
775     
776     ResourceRequest request([URL absoluteURL]);
777
778     // hack because Mail checks for this property to detect data / archive loads
779     [NSURLProtocol setProperty:@"" forKey:@"WebDataRequest" inRequest:(NSMutableURLRequest *)request.nsURLRequest()];
780
781     SubstituteData substituteData(WebCore::SharedBuffer::wrapNSData(data), MIMEType, encodingName, [unreachableURL absoluteURL], responseURL);
782
783     [self _frameLoader]->load(request, substituteData);
784 }
785
786
787 - (void)loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)URL
788 {
789     if (!MIMEType)
790         MIMEType = @"text/html";
791     [self _loadData:data MIMEType:MIMEType textEncodingName:encodingName baseURL:URL unreachableURL:nil];
792 }
793
794 - (void)_loadHTMLString:(NSString *)string baseURL:(NSURL *)URL unreachableURL:(NSURL *)unreachableURL
795 {
796     NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
797     [self _loadData:data MIMEType:@"text/html" textEncodingName:@"UTF-8" baseURL:URL unreachableURL:unreachableURL];
798 }
799
800 - (void)loadHTMLString:(NSString *)string baseURL:(NSURL *)URL
801 {
802     [self _loadHTMLString:string baseURL:URL unreachableURL:nil];
803 }
804
805 - (void)loadAlternateHTMLString:(NSString *)string baseURL:(NSURL *)URL forUnreachableURL:(NSURL *)unreachableURL
806 {
807     [self _loadHTMLString:string baseURL:URL unreachableURL:unreachableURL];
808 }
809
810 - (void)loadArchive:(WebArchive *)archive
811 {
812     WebResource *mainResource = [archive mainResource];
813     if (mainResource) {
814         SubstituteData substituteData(WebCore::SharedBuffer::wrapNSData([mainResource data]), [mainResource MIMEType], [mainResource textEncodingName], KURL());
815         ResourceRequest request([mainResource URL]);
816
817         // hack because Mail checks for this property to detect data / archive loads
818         [NSURLProtocol setProperty:@"" forKey:@"WebDataRequest" inRequest:(NSMutableURLRequest *)request.nsURLRequest()];
819
820         RefPtr<DocumentLoader> documentLoader = core(self)->loader()->client()->createDocumentLoader(request, substituteData);
821
822         [dataSource(documentLoader.get()) _addToUnarchiveState:archive];
823
824         [self _frameLoader]->load(documentLoader.get());
825     }
826 }
827
828 - (void)stopLoading
829 {
830     if (FrameLoader* frameLoader = [self _frameLoader])
831         frameLoader->stopForUserCancel();
832 }
833
834 - (void)reload
835 {
836     [self _frameLoader]->reload();
837 }
838
839 - (WebFrame *)findFrameNamed:(NSString *)name
840 {
841     Frame* coreFrame = core(self);
842     if (!coreFrame)
843         return nil;
844     return kit(coreFrame->tree()->find(name));
845 }
846
847 - (WebFrame *)parentFrame
848 {
849     Frame* coreFrame = core(self);
850     if (!coreFrame)
851         return nil;
852     return [[kit(coreFrame->tree()->parent()) retain] autorelease];
853 }
854
855 - (NSArray *)childFrames
856 {
857     Frame* coreFrame = core(self);
858     if (!coreFrame)
859         return [NSArray array];
860     NSMutableArray *children = [NSMutableArray arrayWithCapacity:coreFrame->tree()->childCount()];
861     for (Frame* child = coreFrame->tree()->firstChild(); child; child = child->tree()->nextSibling())
862         [children addObject:kit(child)];
863     return children;
864 }
865
866 - (WebScriptObject *)windowObject
867 {
868     Frame* coreFrame = core(self);
869     if (!coreFrame)
870         return 0;
871     return coreFrame->windowScriptObject();
872 }
873
874 - (JSGlobalContextRef)globalContext
875 {
876     Frame* coreFrame = core(self);
877     if (!coreFrame)
878         return 0;
879     return reinterpret_cast<JSGlobalContextRef>(coreFrame->scriptProxy()->interpreter()->globalExec());
880 }
881
882 @end