webengine/osswebengine/WebKit/WebView/WebFrame.mm
changeset 0 dd21522fd290
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/webengine/osswebengine/WebKit/WebView/WebFrame.mm	Mon Mar 30 12:54:55 2009 +0300
@@ -0,0 +1,882 @@
+/*
+ * Copyright (C) 2005, 2006 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "WebFrameInternal.h"
+
+#import "DOMCSSStyleDeclarationInternal.h"
+#import "DOMDocumentInternal.h"
+#import "DOMElementInternal.h"
+#import "DOMHTMLElementInternal.h"
+#import "DOMNodeInternal.h"
+#import "DOMRangeInternal.h"
+#import "WebBackForwardList.h"
+#import "WebChromeClient.h"
+#import "WebDataSourceInternal.h"
+#import "WebDocumentInternal.h"
+#import "WebDocumentLoaderMac.h"
+#import "WebFrameBridge.h"
+#import "WebFrameLoadDelegate.h"
+#import "WebFrameLoaderClient.h"
+#import "WebFrameViewInternal.h"
+#import "WebHTMLViewInternal.h"
+#import "WebHistoryItem.h"
+#import "WebHistoryItemInternal.h"
+#import "WebHistoryItemPrivate.h"
+#import "WebKitLogging.h"
+#import "WebKitStatisticsPrivate.h"
+#import "WebNSURLExtras.h"
+#import "WebNSURLRequestExtras.h"
+#import "WebNetscapePluginEmbeddedView.h"
+#import "WebNullPluginView.h"
+#import "WebPlugin.h"
+#import "WebPluginController.h"
+#import "WebPreferencesPrivate.h"
+#import "WebScriptDebugDelegatePrivate.h"
+#import "WebViewInternal.h"
+#import <WebCore/Chrome.h>
+#import <WebCore/ColorMac.h>
+#import <WebCore/Document.h>
+#import <WebCore/Event.h>
+#import <WebCore/FrameLoader.h>
+#import <WebCore/Frame.h>
+#import <WebCore/FrameTree.h>
+#import <WebCore/HistoryItem.h>
+#import <WebCore/HTMLFormElement.h>
+#import <WebCore/HTMLFrameOwnerElement.h>
+#import <WebCore/Page.h>
+#import <WebCore/SelectionController.h>
+#import <WebCore/SharedBuffer.h>
+#import <WebCore/FormState.h>
+#import <WebCore/ResourceRequest.h>
+#import <WebCore/kjs_binding.h>
+#import <WebCore/kjs_proxy.h>
+#import <WebKit/DOMDocument.h>
+#import <WebKit/DOMElement.h>
+#import <WebKit/DOMHTMLElement.h>
+#import <WebKit/DOMNode.h>
+#import <WebKit/DOMRange.h>
+
+using namespace WebCore;
+
+/*
+Here is the current behavior matrix for four types of navigations:
+
+Standard Nav:
+
+ Restore form state:   YES
+ Restore scroll and focus state:  YES
+ Cache policy: NSURLRequestUseProtocolCachePolicy
+ Add to back/forward list: YES
+ 
+Back/Forward:
+
+ Restore form state:   YES
+ Restore scroll and focus state:  YES
+ Cache policy: NSURLRequestReturnCacheDataElseLoad
+ Add to back/forward list: NO
+
+Reload (meaning only the reload button):
+
+ Restore form state:   NO
+ Restore scroll and focus state:  YES
+ Cache policy: NSURLRequestReloadIgnoringCacheData
+ Add to back/forward list: NO
+
+Repeat load of the same URL (by any other means of navigation other than the reload button, including hitting return in the location field):
+
+ Restore form state:   NO
+ Restore scroll and focus state:  NO, reset to initial conditions
+ Cache policy: NSURLRequestReloadIgnoringCacheData
+ Add to back/forward list: NO
+*/
+
+using namespace WebCore;
+
+NSString *WebPageCacheEntryDateKey = @"WebPageCacheEntryDateKey";
+NSString *WebPageCacheDataSourceKey = @"WebPageCacheDataSourceKey";
+NSString *WebPageCacheDocumentViewKey = @"WebPageCacheDocumentViewKey";
+
+@interface WebFrame (ForwardDecls)
+- (void)_loadHTMLString:(NSString *)string baseURL:(NSURL *)URL unreachableURL:(NSURL *)unreachableURL;
+- (WebHistoryItem *)_createItem:(BOOL)useOriginal;
+- (WebHistoryItem *)_createItemTreeWithTargetFrame:(WebFrame *)targetFrame clippedAtTarget:(BOOL)doClip;
+@end
+
+@interface NSView (WebFramePluginHosting)
+- (void)setWebFrame:(WebFrame *)webFrame;
+@end
+
+@implementation WebFramePrivate
+
+- (void)dealloc
+{
+    [webFrameView release];
+    
+    [scriptDebugger release];
+
+    [super dealloc];
+}
+
+- (void)setWebFrameView:(WebFrameView *)v 
+{ 
+    [v retain];
+    [webFrameView release];
+    webFrameView = v;
+}
+
+@end
+
+CSSStyleDeclaration* core(DOMCSSStyleDeclaration *declaration)
+{
+    return [declaration _CSSStyleDeclaration];
+}
+
+DOMCSSStyleDeclaration *kit(WebCore::CSSStyleDeclaration* declaration)
+{
+    return [DOMCSSStyleDeclaration _wrapCSSStyleDeclaration:declaration];
+}
+
+Element* core(DOMElement *element)
+{
+    return [element _element];
+}
+
+DOMElement *kit(Element* element)
+{
+    return [DOMElement _wrapElement:element];
+}
+
+Node* core(DOMNode *node)
+{
+    return [node _node];
+}
+
+DOMNode *kit(Node* node)
+{
+    return [DOMNode _wrapNode:node];
+}
+
+DOMNode *kit(PassRefPtr<Node> node)
+{
+    return [DOMNode _wrapNode:node.get()];
+}
+
+Document* core(DOMDocument *document)
+{
+    return [document _document];
+}
+
+DOMDocument *kit(Document* document)
+{
+    return [DOMDocument _wrapDocument:document];
+}
+
+HTMLElement* core(DOMHTMLElement *element)
+{
+    return [element _HTMLElement];
+}
+
+DOMHTMLElement *kit(HTMLElement *element)
+{
+    return [DOMHTMLElement _wrapHTMLElement:element];
+}
+
+Range* core(DOMRange *range)
+{
+    return [range _range];
+}
+
+DOMRange *kit(Range* range)
+{
+    return [DOMRange _wrapRange:range];
+}
+
+WebCore::EditableLinkBehavior core(WebKitEditableLinkBehavior editableLinkBehavior)
+{
+    return static_cast<WebCore::EditableLinkBehavior>(editableLinkBehavior);
+}
+
+WebKitEditableLinkBehavior kit(WebCore::EditableLinkBehavior editableLinkBehavior)
+{
+    return static_cast<WebKitEditableLinkBehavior>(editableLinkBehavior);
+}
+
+@implementation WebFrame (WebInternal)
+
+
+static inline WebFrame *frame(WebCoreFrameBridge *bridge)
+{
+    return ((WebFrameBridge *)bridge)->_frame;
+}
+
+Frame* core(WebFrame *frame)
+{
+    if (!frame)
+        return 0;
+    
+    if (!frame->_private->bridge)
+        return 0;
+
+    return frame->_private->bridge->m_frame;
+}
+
+WebFrame *kit(Frame* frame)
+{
+    return frame ? ((WebFrameBridge *)frame->bridge())->_frame : nil;
+}
+
+Page* core(WebView *webView)
+{
+    return [webView page];
+}
+
+WebView *kit(Page* page)
+{
+    return page ? static_cast<WebChromeClient*>(page->chrome()->client())->webView() : nil;
+}
+
+WebView *getWebView(WebFrame *webFrame)
+{
+    Frame* coreFrame = core(webFrame);
+    if (!coreFrame)
+        return nil;
+    return kit(coreFrame->page());
+}
+
+/*
+    In the case of saving state about a page with frames, we store a tree of items that mirrors the frame tree.  
+    The item that was the target of the user's navigation is designated as the "targetItem".  
+    When this method is called with doClip=YES we're able to create the whole tree except for the target's children, 
+    which will be loaded in the future.  That part of the tree will be filled out as the child loads are committed.
+*/
+
++ (CFAbsoluteTime)_timeOfLastCompletedLoad
+{
+    return FrameLoader::timeOfLastCompletedLoad() - kCFAbsoluteTimeIntervalSince1970;
+}
+
+- (WebFrameBridge *)_bridge
+{
+    return _private->bridge;
+}
+
+- (void)_loadURL:(NSURL *)URL referrer:(NSString *)referrer intoChild:(WebFrame *)childFrame
+{
+    ASSERT(childFrame);
+    HistoryItem* parentItem = core(self)->loader()->currentHistoryItem();
+    FrameLoadType loadType = [self _frameLoader]->loadType();
+    FrameLoadType childLoadType = FrameLoadTypeRedirectWithLockedHistory;
+
+    // If we're moving in the backforward list, we might want to replace the content
+    // of this child frame with whatever was there at that point.
+    // Reload will maintain the frame contents, LoadSame will not.
+    if (parentItem && parentItem->children().size() &&
+        (isBackForwardLoadType(loadType)
+         || loadType == FrameLoadTypeReload
+         || loadType == FrameLoadTypeReloadAllowingStaleData))
+    {
+        HistoryItem* childItem = parentItem->childItemWithName([childFrame name]);
+        if (childItem) {
+            // Use the original URL to ensure we get all the side-effects, such as
+            // onLoad handlers, of any redirects that happened. An example of where
+            // this is needed is Radar 3213556.
+            URL = [NSURL _web_URLWithDataAsString:childItem->originalURLString()];
+            // These behaviors implied by these loadTypes should apply to the child frames
+            childLoadType = loadType;
+
+            if (isBackForwardLoadType(loadType))
+                // For back/forward, remember this item so we can traverse any child items as child frames load
+                core(childFrame)->loader()->setProvisionalHistoryItem(childItem);
+            else
+                // For reload, just reinstall the current item, since a new child frame was created but we won't be creating a new BF item
+                core(childFrame)->loader()->setCurrentHistoryItem(childItem);
+        }
+    }
+
+    WebArchive *archive = [[self _dataSource] _popSubframeArchiveWithName:[childFrame name]];
+    if (archive)
+        [childFrame loadArchive:archive];
+    else
+        [childFrame _frameLoader]->load([URL absoluteURL], referrer, childLoadType,
+                                        String(), 0, 0);
+}
+
+
+- (void)_viewWillMoveToHostWindow:(NSWindow *)hostWindow
+{
+    Frame* coreFrame = core(self);
+    for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
+        [[[kit(frame) frameView] documentView] viewWillMoveToHostWindow:hostWindow];
+}
+
+- (void)_viewDidMoveToHostWindow
+{
+    Frame* coreFrame = core(self);
+    for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
+        [[[kit(frame) frameView] documentView] viewDidMoveToHostWindow];
+}
+
+- (void)_addChild:(WebFrame *)child
+{
+    core(self)->tree()->appendChild(adoptRef(core(child)));
+    if ([child _dataSource])
+        [[child _dataSource] _documentLoader]->setOverrideEncoding([[self _dataSource] _documentLoader]->overrideEncoding());  
+}
+
+- (int)_numPendingOrLoadingRequests:(BOOL)recurse
+{
+    return core(self)->loader()->numPendingOrLoadingRequests(recurse);
+}
+
+- (void)_reloadForPluginChanges
+{
+    Frame* coreFrame = core(self);
+    for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
+        NSView <WebDocumentView> *documentView = [[kit(frame) frameView] documentView];
+        if (([documentView isKindOfClass:[WebHTMLView class]] && coreFrame->loader()->containsPlugins()))
+            [kit(frame) reload];
+    }
+}
+
+- (void)_attachScriptDebugger
+{
+    if (!_private->scriptDebugger && core(self)->scriptProxy()->haveInterpreter())
+        _private->scriptDebugger = [[WebScriptDebugger alloc] initWithWebFrame:self];
+}
+
+- (void)_detachScriptDebugger
+{
+    if (_private->scriptDebugger) {
+        id old = _private->scriptDebugger;
+        _private->scriptDebugger = nil;
+        [old release];
+    }
+}
+
+- (id)_initWithWebFrameView:(WebFrameView *)fv webView:(WebView *)v bridge:(WebFrameBridge *)bridge
+{
+    self = [super init];
+    if (!self)
+        return nil;
+
+    _private = [[WebFramePrivate alloc] init];
+    _private->bridge = bridge;
+
+    if (fv) {
+        [_private setWebFrameView:fv];
+        [fv _setWebFrame:self];
+    }
+
+    ++WebFrameCount;
+
+    return self;
+}
+
+- (NSArray *)_documentViews
+{
+    NSMutableArray *result = [NSMutableArray array];
+    Frame* coreFrame = core(self);
+    for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
+        id docView = [[kit(frame) frameView] documentView];
+        if (docView)
+            [result addObject:docView];
+    }
+    return result;
+}
+
+- (void)_updateBackground
+{
+    BOOL drawsBackground = [getWebView(self) drawsBackground];
+    NSColor *backgroundColor = [getWebView(self) backgroundColor];
+
+    Frame* coreFrame = core(self);
+    for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
+        WebFrameBridge *bridge = (WebFrameBridge *)frame->bridge();
+        WebFrame *webFrame = [bridge webFrame];
+        // Never call setDrawsBackground:YES here on the scroll view or the background color will
+        // flash between pages loads. setDrawsBackground:YES will be called in _frameLoadCompleted.
+        if (!drawsBackground)
+            [[[webFrame frameView] _scrollView] setDrawsBackground:NO];
+        [[[webFrame frameView] _scrollView] setBackgroundColor:backgroundColor];
+        id documentView = [[webFrame frameView] documentView];
+        if ([documentView respondsToSelector:@selector(setDrawsBackground:)])
+            [documentView setDrawsBackground:drawsBackground];
+        if ([documentView respondsToSelector:@selector(setBackgroundColor:)])
+            [documentView setBackgroundColor:backgroundColor];
+        [bridge setDrawsBackground:drawsBackground];
+        [bridge setBaseBackgroundColor:backgroundColor];
+    }
+}
+
+- (void)_setInternalLoadDelegate:(id)internalLoadDelegate
+{
+    _private->internalLoadDelegate = internalLoadDelegate;
+}
+
+- (id)_internalLoadDelegate
+{
+    return _private->internalLoadDelegate;
+}
+
+#ifndef BUILDING_ON_TIGER
+- (void)_unmarkAllBadGrammar
+{
+    Frame* coreFrame = core(self);
+    for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
+        Document *doc = frame->document();
+        if (!doc)
+            return;
+
+        doc->removeMarkers(DocumentMarker::Grammar);
+    }
+}
+#endif
+
+- (void)_unmarkAllMisspellings
+{
+    Frame* coreFrame = core(self);
+    for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
+        Document *doc = frame->document();
+        if (!doc)
+            return;
+
+        doc->removeMarkers(DocumentMarker::Spelling);
+    }
+}
+
+- (BOOL)_hasSelection
+{
+    id documentView = [_private->webFrameView documentView];    
+
+    // optimization for common case to avoid creating potentially large selection string
+    if ([documentView isKindOfClass:[WebHTMLView class]])
+        if (Frame* coreFrame = core(self))
+            return coreFrame->selectionController()->isRange();
+
+    if ([documentView conformsToProtocol:@protocol(WebDocumentText)])
+        return [[documentView selectedString] length] > 0;
+    
+    return NO;
+}
+
+- (void)_clearSelection
+{
+    id documentView = [_private->webFrameView documentView];    
+    if ([documentView conformsToProtocol:@protocol(WebDocumentText)])
+        [documentView deselectAll];
+}
+
+#if !ASSERT_DISABLED
+- (BOOL)_atMostOneFrameHasSelection
+{
+    // FIXME: 4186050 is one known case that makes this debug check fail.
+    BOOL found = NO;
+    Frame* coreFrame = core(self);
+    for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
+        if ([kit(frame) _hasSelection]) {
+            if (found)
+                return NO;
+            found = YES;
+        }
+    return YES;
+}
+#endif
+
+- (WebFrame *)_findFrameWithSelection
+{
+    Frame* coreFrame = core(self);
+    for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
+        if ([kit(frame) _hasSelection])
+            return kit(frame);
+    return nil;
+}
+
+- (void)_clearSelectionInOtherFrames
+{
+    // We rely on WebDocumentSelection protocol implementors to call this method when they become first 
+    // responder. It would be nicer to just notice first responder changes here instead, but there's no 
+    // notification sent when the first responder changes in general (Radar 2573089).
+    WebFrame *frameWithSelection = [[getWebView(self) mainFrame] _findFrameWithSelection];
+    if (frameWithSelection != self)
+        [frameWithSelection _clearSelection];
+
+    // While we're in the general area of selection and frames, check that there is only one now.
+    ASSERT([[getWebView(self) mainFrame] _atMostOneFrameHasSelection]);
+}
+
+- (BOOL)_isMainFrame
+{
+   Frame* coreFrame = core(self);
+   if (!coreFrame)
+       return NO;
+   return coreFrame == coreFrame->page()->mainFrame() ;
+}
+
+- (FrameLoader*)_frameLoader
+{
+    Frame* frame = core(self);
+    return frame ? frame->loader() : 0;
+}
+
+static inline WebDataSource *dataSource(DocumentLoader* loader)
+{
+    return loader ? static_cast<WebDocumentLoaderMac*>(loader)->dataSource() : nil;
+}
+
+- (WebDataSource *)_dataSourceForDocumentLoader:(DocumentLoader*)loader
+{
+    return dataSource(loader);
+}
+
+- (void)_addDocumentLoader:(DocumentLoader*)loader toUnarchiveState:(WebArchive *)archive
+{
+    [dataSource(loader) _addToUnarchiveState:archive];
+}
+
+- (WebDataSource *)_dataSource
+{
+    FrameLoader* frameLoader = [self _frameLoader];
+
+    if (!frameLoader)
+        return nil;
+
+    return dataSource(frameLoader->documentLoader());
+}
+
+@end
+
+@implementation WebFrame (WebPrivate)
+
+// FIXME: Yhis exists only as a convenience for Safari, consider moving there.
+- (BOOL)_isDescendantOfFrame:(WebFrame *)ancestor
+{
+    Frame* coreFrame = core(self);
+    return coreFrame && coreFrame->tree()->isDescendantOf(core(ancestor));
+}
+
+- (void)_setShouldCreateRenderers:(BOOL)frame
+{
+    [_private->bridge setShouldCreateRenderers:frame];
+}
+
+- (NSColor *)_bodyBackgroundColor
+{
+    Document* document = core(self)->document();
+    if (!document)
+        return nil;
+    HTMLElement* body = document->body();
+    if (!body)
+        return nil;
+    RenderObject* bodyRenderer = body->renderer();
+    if (!bodyRenderer)
+        return nil;
+    Color color = bodyRenderer->style()->backgroundColor();
+    if (!color.isValid())
+        return nil;
+    return nsColor(color);
+}
+
+- (BOOL)_isFrameSet
+{
+    return core(self)->isFrameSet();
+}
+
+- (BOOL)_firstLayoutDone
+{
+    return [self _frameLoader]->firstLayoutDone();
+}
+
+- (WebFrameLoadType)_loadType
+{
+    return (WebFrameLoadType)[self _frameLoader]->loadType();
+}
+
+#ifndef __LP64__
+- (void)_recursive_resumeNullEventsForAllNetscapePlugins
+{
+    Frame* coreFrame = core(self);
+    for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
+        NSView <WebDocumentView> *documentView = [[kit(frame) frameView] documentView];
+        if ([documentView isKindOfClass:[WebHTMLView class]])
+            [(WebHTMLView *)documentView _resumeNullEventsForAllNetscapePlugins];
+    }
+}
+#endif
+
+#ifndef __LP64__
+- (void)_recursive_pauseNullEventsForAllNetscapePlugins
+{
+    Frame* coreFrame = core(self);
+    for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
+        NSView <WebDocumentView> *documentView = [[kit(frame) frameView] documentView];
+        if ([documentView isKindOfClass:[WebHTMLView class]])
+            [(WebHTMLView *)documentView _pauseNullEventsForAllNetscapePlugins];
+    }
+}
+#endif
+
+- (NSRange)_selectedNSRange
+{
+    return [_private->bridge selectedNSRange];
+}
+
+- (void)_selectNSRange:(NSRange)range
+{
+    [_private->bridge selectNSRange:range];
+}
+
+- (BOOL)_isDisplayingStandaloneImage
+{
+    Document* document = core(self)->document();
+    return document && document->isImageDocument();
+}
+
+@end
+
+@implementation WebFrame
+
+- (id)init
+{
+    return nil;
+}
+
+// Should be deprecated.
+- (id)initWithName:(NSString *)name webFrameView:(WebFrameView *)view webView:(WebView *)webView
+{
+    return nil;
+}
+
+- (void)dealloc
+{
+    ASSERT(_private->bridge == nil);
+    [_private release];
+    --WebFrameCount;
+    [super dealloc];
+}
+
+- (void)finalize
+{
+    ASSERT(_private->bridge == nil);
+    --WebFrameCount;
+    [super finalize];
+}
+
+- (NSString *)name
+{
+    Frame* coreFrame = core(self);
+    if (!coreFrame)
+        return nil;
+    return coreFrame->tree()->name();
+}
+
+- (WebFrameView *)frameView
+{
+    return _private->webFrameView;
+}
+
+- (WebView *)webView
+{
+    return getWebView(self);
+}
+
+- (DOMDocument *)DOMDocument
+{
+    Frame* coreFrame = core(self);
+    if (!coreFrame)
+        return nil;
+    
+    // FIXME: <rdar://problem/5145841> When loading a custom view/representation 
+    // into a web frame, the old document can still be around. This makes sure that
+    // we'll return nil in those cases.
+    if (![[self _dataSource] _isDocumentHTML]) 
+        return nil; 
+
+    Document* document = coreFrame->document();
+    
+    // According to the documentation, we should return nil if the frame doesn't have a document.
+    // While full-frame images and plugins do have an underlying HTML document, we return nil here to be
+    // backwards compatible.
+    if (document && (document->isPluginDocument() || document->isImageDocument()))
+        return nil;
+    
+    return kit(coreFrame->document());
+}
+
+- (DOMHTMLElement *)frameElement
+{
+    Frame* coreFrame = core(self);
+    if (!coreFrame)
+        return nil;
+    return kit(coreFrame->ownerElement());
+}
+
+- (WebDataSource *)provisionalDataSource
+{
+    FrameLoader* frameLoader = [self _frameLoader];
+    return frameLoader ? dataSource(frameLoader->provisionalDocumentLoader()) : nil;
+}
+
+- (WebDataSource *)dataSource
+{
+    FrameLoader* loader = [self _frameLoader];
+    if (!loader || !loader->frameHasLoaded())
+        return nil;
+
+    return [self _dataSource];
+}
+
+- (void)loadRequest:(NSURLRequest *)request
+{
+    [self _frameLoader]->load(request);
+}
+
+static NSURL *createUniqueWebDataURL()
+{
+    CFUUIDRef UUIDRef = CFUUIDCreate(kCFAllocatorDefault);
+    NSString *UUIDString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, UUIDRef);
+    CFRelease(UUIDRef);
+    NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:@"applewebdata://%@", UUIDString]];
+    CFRelease(UUIDString);
+    return URL;
+}
+
+- (void)_loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)URL unreachableURL:(NSURL *)unreachableURL
+{
+    KURL responseURL;
+    if (!URL) {
+        URL = [NSURL URLWithString:@"about:blank"];
+        responseURL = createUniqueWebDataURL();
+    }
+    
+    ResourceRequest request([URL absoluteURL]);
+
+    // hack because Mail checks for this property to detect data / archive loads
+    [NSURLProtocol setProperty:@"" forKey:@"WebDataRequest" inRequest:(NSMutableURLRequest *)request.nsURLRequest()];
+
+    SubstituteData substituteData(WebCore::SharedBuffer::wrapNSData(data), MIMEType, encodingName, [unreachableURL absoluteURL], responseURL);
+
+    [self _frameLoader]->load(request, substituteData);
+}
+
+
+- (void)loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)URL
+{
+    if (!MIMEType)
+        MIMEType = @"text/html";
+    [self _loadData:data MIMEType:MIMEType textEncodingName:encodingName baseURL:URL unreachableURL:nil];
+}
+
+- (void)_loadHTMLString:(NSString *)string baseURL:(NSURL *)URL unreachableURL:(NSURL *)unreachableURL
+{
+    NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
+    [self _loadData:data MIMEType:@"text/html" textEncodingName:@"UTF-8" baseURL:URL unreachableURL:unreachableURL];
+}
+
+- (void)loadHTMLString:(NSString *)string baseURL:(NSURL *)URL
+{
+    [self _loadHTMLString:string baseURL:URL unreachableURL:nil];
+}
+
+- (void)loadAlternateHTMLString:(NSString *)string baseURL:(NSURL *)URL forUnreachableURL:(NSURL *)unreachableURL
+{
+    [self _loadHTMLString:string baseURL:URL unreachableURL:unreachableURL];
+}
+
+- (void)loadArchive:(WebArchive *)archive
+{
+    WebResource *mainResource = [archive mainResource];
+    if (mainResource) {
+        SubstituteData substituteData(WebCore::SharedBuffer::wrapNSData([mainResource data]), [mainResource MIMEType], [mainResource textEncodingName], KURL());
+        ResourceRequest request([mainResource URL]);
+
+        // hack because Mail checks for this property to detect data / archive loads
+        [NSURLProtocol setProperty:@"" forKey:@"WebDataRequest" inRequest:(NSMutableURLRequest *)request.nsURLRequest()];
+
+        RefPtr<DocumentLoader> documentLoader = core(self)->loader()->client()->createDocumentLoader(request, substituteData);
+
+        [dataSource(documentLoader.get()) _addToUnarchiveState:archive];
+
+        [self _frameLoader]->load(documentLoader.get());
+    }
+}
+
+- (void)stopLoading
+{
+    if (FrameLoader* frameLoader = [self _frameLoader])
+        frameLoader->stopForUserCancel();
+}
+
+- (void)reload
+{
+    [self _frameLoader]->reload();
+}
+
+- (WebFrame *)findFrameNamed:(NSString *)name
+{
+    Frame* coreFrame = core(self);
+    if (!coreFrame)
+        return nil;
+    return kit(coreFrame->tree()->find(name));
+}
+
+- (WebFrame *)parentFrame
+{
+    Frame* coreFrame = core(self);
+    if (!coreFrame)
+        return nil;
+    return [[kit(coreFrame->tree()->parent()) retain] autorelease];
+}
+
+- (NSArray *)childFrames
+{
+    Frame* coreFrame = core(self);
+    if (!coreFrame)
+        return [NSArray array];
+    NSMutableArray *children = [NSMutableArray arrayWithCapacity:coreFrame->tree()->childCount()];
+    for (Frame* child = coreFrame->tree()->firstChild(); child; child = child->tree()->nextSibling())
+        [children addObject:kit(child)];
+    return children;
+}
+
+- (WebScriptObject *)windowObject
+{
+    Frame* coreFrame = core(self);
+    if (!coreFrame)
+        return 0;
+    return coreFrame->windowScriptObject();
+}
+
+- (JSGlobalContextRef)globalContext
+{
+    Frame* coreFrame = core(self);
+    if (!coreFrame)
+        return 0;
+    return reinterpret_cast<JSGlobalContextRef>(coreFrame->scriptProxy()->interpreter()->globalExec());
+}
+
+@end