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