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