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