| /* |
| * Copyright (C) 2005, 2006, 2007, 2008 Apple 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 "WebScriptDebugger.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 "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> |
| #import <JavaScriptCore/APICast.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 *)baseURL 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]; |
| |
| delete scriptDebugger; |
| |
| [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]; |
| } |
| |
| EditableLinkBehavior core(WebKitEditableLinkBehavior editableLinkBehavior) |
| { |
| switch (editableLinkBehavior) { |
| case WebKitEditableLinkDefaultBehavior: |
| return EditableLinkDefaultBehavior; |
| case WebKitEditableLinkAlwaysLive: |
| return EditableLinkAlwaysLive; |
| case WebKitEditableLinkOnlyLiveWithShiftKey: |
| return EditableLinkOnlyLiveWithShiftKey; |
| case WebKitEditableLinkLiveWhenNotFocused: |
| return EditableLinkLiveWhenNotFocused; |
| case WebKitEditableLinkNeverLive: |
| return EditableLinkNeverLive; |
| } |
| ASSERT_NOT_REACHED(); |
| return EditableLinkDefaultBehavior; |
| } |
| |
| @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) |
| return; |
| |
| KJS::JSGlobalObject* globalObject = core(self)->scriptProxy()->globalObject(); |
| if (!globalObject) |
| return; |
| |
| _private->scriptDebugger = new WebScriptDebugger(globalObject); |
| } |
| |
| - (void)_detachScriptDebugger |
| { |
| if (!_private->scriptDebugger) |
| return; |
| |
| delete _private->scriptDebugger; |
| _private->scriptDebugger = 0; |
| } |
| |
| - (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()); |
| } |
| |
| #if ENABLE(NETSCAPE_PLUGIN_API) |
| - (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]; |
| } |
| } |
| |
| - (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 |
| |
| @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(); |
| } |
| |
| - (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 *)baseURL unreachableURL:(NSURL *)unreachableURL |
| { |
| KURL responseURL; |
| if (!baseURL) { |
| baseURL = blankURL(); |
| responseURL = createUniqueWebDataURL(); |
| } |
| |
| ResourceRequest request([baseURL 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 *)baseURL |
| { |
| if (!MIMEType) |
| MIMEType = @"text/html"; |
| [self _loadData:data MIMEType:MIMEType textEncodingName:encodingName baseURL:baseURL unreachableURL:nil]; |
| } |
| |
| - (void)_loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL unreachableURL:(NSURL *)unreachableURL |
| { |
| NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding]; |
| [self _loadData:data MIMEType:@"text/html" textEncodingName:@"UTF-8" baseURL:baseURL unreachableURL:unreachableURL]; |
| } |
| |
| - (void)loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL |
| { |
| [self _loadHTMLString:string baseURL:baseURL unreachableURL:nil]; |
| } |
| |
| - (void)loadAlternateHTMLString:(NSString *)string baseURL:(NSURL *)baseURL forUnreachableURL:(NSURL *)unreachableURL |
| { |
| [self _loadHTMLString:string baseURL:baseURL 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 toGlobalRef(coreFrame->scriptProxy()->globalObject()->globalExec()); |
| } |
| |
| @end |