WebUnarchivingState *unarchivingState;
BOOL supportsMultipartContent;
-
- WebFrameLoader *frameLoader;
}
@end
[responses release];
[webFrame release];
[unarchivingState release];
- [frameLoader release];
[super dealloc];
}
- (void)_updateLoading
{
- [self _setLoading:[_private->frameLoader isLoading]];
+ [self _setLoading:[[_private->webFrame _frameLoader] isLoading]];
}
- (void)_setData:(NSData *)data
{
// Don't load an icon if 1) this is not the main frame 2) we ended in error
// 3) we already did 4) they aren't saved by the DB.
- if ([self webFrame] != [[self _webView] mainFrame] || _private->mainDocumentError || [_private->frameLoader hasIconLoader] ||
+ if ([self webFrame] != [[self _webView] mainFrame] || _private->mainDocumentError || [[_private->webFrame _frameLoader] hasIconLoader] ||
![[WebIconDatabase sharedIconDatabase] _isEnabled]) {
return;
}
} else {
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:_private->iconURL];
[[self webFrame] _addExtraFieldsToRequest:request mainResource:YES alwaysFromRequest:NO];
- [_private->frameLoader loadIconWithRequest:request];
+ [[_private->webFrame _frameLoader] loadIconWithRequest:request];
[request release];
}
}
// there's no callback for that.
[self _loadIcon];
- if ([_private->frameLoader isLoadingMainResource]) {
- [self _setData:[_private->frameLoader mainResourceData]];
- [_private->frameLoader releaseMainResourceLoader];
+ if ([[_private->webFrame _frameLoader] isLoadingMainResource]) {
+ [self _setData:[[_private->webFrame _frameLoader] mainResourceData]];
+ [[_private->webFrame _frameLoader] releaseMainResourceLoader];
}
[self _updateLoading];
{
// Always attempt to stop the icon loader because it may still be loading after the data source
// is done loading and not stopping it can cause a world leak.
- [_private->frameLoader stopLoadingIcon];
+ [[_private->webFrame _frameLoader] stopLoadingIcon];
// The same goes for the bridge/part, which may still be parsing.
if (_private->committed)
_private->stopping = YES;
- if ([_private->frameLoader isLoadingMainResource]) {
+ if ([[_private->webFrame _frameLoader] isLoadingMainResource]) {
// Stop the main resource loader and let it send the cancelled message.
- [_private->frameLoader cancelMainResourceLoad];
- } else if ([_private->frameLoader isLoadingSubresources]) {
+ [[_private->webFrame _frameLoader] cancelMainResourceLoad];
+ } else if ([[_private->webFrame _frameLoader] isLoadingSubresources]) {
// The main resource loader already finished loading. Set the cancelled error on the
// document and let the subresourceLoaders send individual cancelled messages below.
[self _setMainDocumentError:[self _cancelledError]];
[self _mainReceivedError:[self _cancelledError] complete:YES];
}
- [_private->frameLoader stopLoadingSubresources];
+ [[_private->webFrame _frameLoader] stopLoadingSubresources];
// FIXME: why not stop loading plugins here?
_private->stopping = NO;
{
[self _prepareForLoadStart];
- if ([_private->frameLoader isLoadingMainResource])
+ if ([[_private->webFrame _frameLoader] isLoadingMainResource])
return;
_private->loadingFromPageCache = NO;
else
identifier = [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:[self _webView] identifierForInitialRequest:_private->originalRequest fromDataSource:self];
- if (![_private->frameLoader startLoadingMainResourceWithRequest:_private->request identifier:identifier])
+ if (![[_private->webFrame _frameLoader] startLoadingMainResourceWithRequest:_private->request identifier:identifier])
[self _updateLoading];
}
- (void)_addSubresourceLoader:(WebLoader *)loader
{
- [_private->frameLoader addSubresourceLoader:loader];
+ [[_private->webFrame _frameLoader] addSubresourceLoader:loader];
[self _setLoading:YES];
}
- (void)_removeSubresourceLoader:(WebLoader *)loader
{
- [_private->frameLoader removeSubresourceLoader:loader];
+ [[_private->webFrame _frameLoader] removeSubresourceLoader:loader];
[self _updateLoading];
}
- (void)_addPlugInStreamLoader:(WebLoader *)loader
{
- [_private->frameLoader addPlugInStreamLoader:loader];
+ [[_private->webFrame _frameLoader] addPlugInStreamLoader:loader];
[self _setLoading:YES];
}
- (void)_removePlugInStreamLoader:(WebLoader *)loader
{
- [_private->frameLoader removePlugInStreamLoader:loader];
+ [[_private->webFrame _frameLoader] removePlugInStreamLoader:loader];
[self _updateLoading];
}
}
_private->defersCallbacks = defers;
- [_private->frameLoader setDefersCallbacks:defers];
+ [[_private->webFrame _frameLoader] setDefersCallbacks:defers];
}
- (BOOL)_defersCallbacks
- (void)_stopLoadingWithError:(NSError *)error
{
- [_private->frameLoader stopLoadingWithError:error];
+ [[_private->webFrame _frameLoader] stopLoadingWithError:error];
}
- (void)_setWebFrame:(WebFrame *)frame
- (void)_revertToProvisionalState
{
[self _setRepresentation:nil];
- [[self webFrame] _setupForReplace];
+ [[_private->webFrame _frameLoader] setupForReplace];
_private->committed = NO;
}
if ([self _doesProgressiveLoadWithMIMEType:newMIMEType])
[self _revertToProvisionalState];
- [_private->frameLoader stopLoadingSubresources];
- [_private->frameLoader stopLoadingPlugIns];
+ [[_private->webFrame _frameLoader] stopLoadingSubresources];
+ [[_private->webFrame _frameLoader] stopLoadingPlugIns];
[_private->unarchivingState release];
}
_private->request = [_private->originalRequest mutableCopy];
_private->supportsMultipartContent = WKSupportsMultipartXMixedReplace(_private->request);
- _private->frameLoader = [[WebFrameLoader alloc] initWithDataSource:self];
-
++WebDataSourceCount;
return self;
- (NSData *)data
{
- return _private->resourceData != nil ? _private->resourceData : [_private->frameLoader mainResourceData];
+ return _private->resourceData != nil ? _private->resourceData : [[_private->webFrame _frameLoader] mainResourceData];
}
- (id <WebDocumentRepresentation>)representation
{
// Once a frame has loaded, we no longer need to consider subresources,
// but we still need to consider subframes.
- if ([[self webFrame] _state] != WebFrameStateComplete) {
+ if ([[[self webFrame] _frameLoader] state] != WebFrameStateComplete) {
if (!_private->primaryLoadComplete && _private->loading)
return YES;
- if ([_private->frameLoader isLoadingSubresources])
+ if ([[_private->webFrame _frameLoader] isLoadingSubresources])
return YES;
if (![[[self webFrame] _bridge] doneProcessingData])
return YES;
#import <WebKit/WebDocumentInternal.h>
#import <WebKit/WebFormDataStream.h>
#import <WebKit/WebFrameLoadDelegate.h>
+#import <WebKit/WebFrameLoader.h>
#import <WebKit/WebFrameViewInternal.h>
#import <WebKit/WebHistoryPrivate.h>
#import <WebKit/WebHistoryItemPrivate.h>
#import <objc/objc-runtime.h>
-#ifndef NDEBUG
-static const char * const stateNames[] = {
- "WebFrameStateProvisional",
- "WebFrameStateCommittedPage",
- "WebFrameStateComplete"
-};
-#endif
-
/*
Here is the current behavior matrix for four types of navigations:
{
@public
WebFrameView *webFrameView;
- WebDataSource *dataSource;
- WebDataSource *provisionalDataSource;
+ WebFrameLoader *frameLoader;
+
WebFrameBridge *bridge;
- WebFrameState state;
WebFrameLoadType loadType;
WebHistoryItem *currentItem; // BF item for our current content
WebHistoryItem *provisionalItem; // BF item for where we're trying to go
- (void)setWebFrameView:(WebFrameView *)v;
- (WebFrameView *)webFrameView;
-- (void)setDataSource:(WebDataSource *)d;
-- (WebDataSource *)dataSource;
-- (void)setProvisionalDataSource:(WebDataSource *)d;
-- (WebDataSource *)provisionalDataSource;
- (WebFrameLoadType)loadType;
- (void)setLoadType:(WebFrameLoadType)loadType;
return nil;
}
- state = WebFrameStateComplete;
loadType = WebFrameLoadTypeStandard;
return self;
- (void)dealloc
{
[webFrameView release];
- [dataSource release];
- [provisionalDataSource release];
[currentItem release];
[provisionalItem release];
webFrameView = v;
}
-- (WebDataSource *)dataSource { return dataSource; }
-- (void)setDataSource: (WebDataSource *)d
-{
- [d retain];
- [dataSource release];
- dataSource = d;
-}
-
-- (WebDataSource *)provisionalDataSource { return provisionalDataSource; }
-- (void)setProvisionalDataSource: (WebDataSource *)d
-{
- ASSERT(!d || !provisionalDataSource);
- [d retain];
- [provisionalDataSource release];
- provisionalDataSource = d;
-}
-
- (WebFrameLoadType)loadType { return loadType; }
- (void)setLoadType: (WebFrameLoadType)t
{
for (WebFrame *child = [self _firstChildFrame]; child; child = [child _nextSiblingFrame])
[child _closeOldDataSources];
- if (_private->dataSource)
+ if ([_private->frameLoader dataSource])
[[[self webView] _frameLoadDelegateForwarder] webView:[self webView] willCloseFrame:self];
[[self webView] setMainFrameDocumentReady:NO]; // stop giving out the actual DOMDocument to observers
}
-- (void)_clearDataSource
-{
- [self _setDataSource:nil];
-}
-
- (void)_detachFromParent
{
WebFrameBridge *bridge = [_private->bridge retain];
[_private->webFrameView _setWebFrame:nil]; // needed for now to be compatible w/ old behavior
- [self _clearDataSource];
+ [_private->frameLoader clearDataSource];
[_private setWebFrameView:nil];
[self retain]; // retain self temporarily because dealloc can re-enter this method
[self release];
}
-- (void)_setDataSource:(WebDataSource *)ds
-{
- if (ds == nil && _private->dataSource == nil) {
- return;
- }
-
- ASSERT(ds != _private->dataSource);
-
- if (_private->dataSource) {
- // Make sure that any work that is triggered by resigning first reponder can get done.
- // The main example where this came up is the textDidEndEditing that is sent to the
- // FormsDelegate (3223413). We need to do this before _detachChildren, since that will
- // remove the views as a side-effect of freeing the bridge, at which point we can't
- // post the FormDelegate messages.
- //
- // Note that this can also take FirstResponder away from a child of our frameView that
- // is not in a child frame's view. This is OK because we are in the process
- // of loading new content, which will blow away all editors in this top frame, and if
- // a non-editor is firstReponder it will not be affected by endEditingFor:.
- // Potentially one day someone could write a DocView whose editors were not all
- // replaced by loading new content, but that does not apply currently.
- NSView *frameView = [self frameView];
- NSWindow *window = [frameView window];
- NSResponder *firstResp = [window firstResponder];
- if ([firstResp isKindOfClass:[NSView class]]
- && [(NSView *)firstResp isDescendantOf:frameView])
- {
- [window endEditingFor:firstResp];
- }
-
- [self _detachChildren];
-
- [_private->dataSource _setWebFrame:nil];
- } else {
- ASSERT(![self _childFrameCount]);
- }
-
- [_private setDataSource:ds];
- [ds _setWebFrame:self];
-}
-
- (void)_setLoadType: (WebFrameLoadType)t
{
[_private setLoadType:t];
- (void)_makeDocumentView
{
- NSView <WebDocumentView> *documentView = [_private->webFrameView _makeDocumentViewForDataSource:_private->dataSource];
- if (!documentView) {
+ NSView <WebDocumentView> *documentView = [_private->webFrameView _makeDocumentViewForDataSource:[_private->frameLoader dataSource]];
+ if (!documentView)
return;
- }
// FIXME: We could save work and not do this for a top-level view that is not a WebHTMLView.
WebFrameView *v = _private->webFrameView;
// Call setDataSource on the document view after it has been placed in the view hierarchy.
// This what we for the top-level view, so should do this for views in subframes as well.
- [documentView setDataSource:_private->dataSource];
+ [documentView setDataSource:[_private->frameLoader dataSource]];
}
- (void)_receivedMainResourceError:(NSError *)error
{
- if ([self _state] == WebFrameStateProvisional) {
- NSURL *failedURL = [[_private->provisionalDataSource _originalRequest] URL];
+ if ([_private->frameLoader state] == WebFrameStateProvisional) {
+ NSURL *failedURL = [[[_private->frameLoader provisionalDataSource] _originalRequest] URL];
// When we are pre-commit, the currentItem is where the pageCache data resides
NSDictionary *pageCache = [[_private currentItem] pageCache];
[[self _bridge] didNotOpenURL:failedURL pageCache:pageCache];
}
}
-- (void)_commitProvisionalLoad
-{
- [self _setDataSource:_private->provisionalDataSource];
- [self _setProvisionalDataSource: nil];
- [self _setState:WebFrameStateCommittedPage];
-}
-
- (void)_transitionToCommitted:(NSDictionary *)pageCache
{
ASSERT([self webView] != nil);
- switch ([self _state]) {
+ switch ([_private->frameLoader state]) {
case WebFrameStateProvisional:
{
[[[[self frameView] _scrollView] contentView] setCopiesOnScroll:YES];
if (loadType == WebFrameLoadTypeForward ||
loadType == WebFrameLoadTypeBack ||
loadType == WebFrameLoadTypeIndexedBackForward ||
- (loadType == WebFrameLoadTypeReload && [_private->provisionalDataSource unreachableURL] != nil))
+ (loadType == WebFrameLoadTypeReload && [[_private->frameLoader provisionalDataSource] unreachableURL] != nil))
{
// Once committed, we want to use current item for saving DocState, and
// the provisional item for restoring state.
// The call to closeURL invokes the unload event handler, which can execute arbitrary
// JavaScript. If the script initiates a new load, we need to abandon the current load,
// or the two will stomp each other.
- WebDataSource *pd = _private->provisionalDataSource;
+ WebDataSource *pd = [_private->frameLoader provisionalDataSource];
[[self _bridge] closeURL];
- if (pd != _private->provisionalDataSource)
+ if (pd != [_private->frameLoader provisionalDataSource])
return;
- [self _commitProvisionalLoad];
+ [_private->frameLoader commitProvisionalLoad];
// Handle adding the URL to the back/forward list.
WebDataSource *ds = [self dataSource];
}
}
-- (WebFrameState)_state
-{
- return _private->state;
-}
-
-static CFAbsoluteTime _timeOfLastCompletedLoad;
+ (CFAbsoluteTime)_timeOfLastCompletedLoad
{
- return _timeOfLastCompletedLoad;
+ return [WebFrameLoader timeOfLastCompletedLoad];
}
- (BOOL)_createPageCacheForItem:(WebHistoryItem *)item
return YES;
}
-- (void)_setState: (WebFrameState)newState
-{
- LOG(Loading, "%@: transition from %s to %s", [self name], stateNames[_private->state], stateNames[newState]);
- if ([self webView])
- LOG(Timing, "%@: transition from %s to %s, %f seconds since start of document load", [self name], stateNames[_private->state], stateNames[newState], CFAbsoluteTimeGetCurrent() - [[[[self webView] mainFrame] dataSource] _loadingStartedTime]);
-
- if (newState == WebFrameStateComplete && self == [[self webView] mainFrame]){
- LOG(DocumentLoad, "completed %@ (%f seconds)", [[[self dataSource] request] URL], CFAbsoluteTimeGetCurrent() - [[self dataSource] _loadingStartedTime]);
- }
-
- _private->state = newState;
-
- if (_private->state == WebFrameStateProvisional) {
- _private->firstLayoutDone = NO;
- [_private->bridge provisionalLoadStarted];
-
- // FIXME: This is OK as long as no one resizes the window,
- // but in the case where someone does, it means garbage outside
- // the occupied part of the scroll view.
- [[[self frameView] _scrollView] setDrawsBackground:NO];
-
- // Cache the page, if possible.
- // Don't write to the cache if in the middle of a redirect, since we will want to
- // store the final page we end up on.
- // No point writing to the cache on a reload or loadSame, since we will just write
- // over it again when we leave that page.
- WebHistoryItem *item = [_private currentItem];
- WebFrameLoadType loadType = [self _loadType];
- if ([self _canCachePage]
- && [_private->bridge canCachePage]
- && item
- && !_private->quickRedirectComing
- && loadType != WebFrameLoadTypeReload
- && loadType != WebFrameLoadTypeReloadAllowingStaleData
- && loadType != WebFrameLoadTypeSame
- && ![[self dataSource] isLoading]
- && ![[self dataSource] _isStopping])
- {
- if ([[[self dataSource] representation] isKindOfClass: [WebHTMLRepresentation class]]) {
- if (![item pageCache]){
-
- // Add the items to this page's cache.
- if ([self _createPageCacheForItem:item]) {
- LOG(PageCache, "Saving page to back/forward cache, %@\n", [[self dataSource] _URL]);
-
- // See if any page caches need to be purged after the addition of this
- // new page cache.
- [self _purgePageCache];
- }
- else {
- LOG(PageCache, "NOT saving page to back/forward cache, unable to create items, %@\n", [[self dataSource] _URL]);
- }
- }
- }
- else {
- // Put the document into a null state, so it can be restored correctly.
- [_private->bridge clear];
- }
- }
- else {
- LOG(PageCache, "NOT saving page to back/forward cache, %@\n", [[self dataSource] _URL]);
- }
- }
-
- if (_private->state == WebFrameStateComplete) {
- NSScrollView *sv = [[self frameView] _scrollView];
- if ([[self webView] drawsBackground])
- [sv setDrawsBackground:YES];
- [_private setPreviousItem:nil];
- _timeOfLastCompletedLoad = CFAbsoluteTimeGetCurrent();
-
- [[self dataSource] _stopRecordingResponses];
-
- // After a canceled provisional load, firstLayoutDone is NO. Reset it to YES if we're displaying a page.
- if (_private->dataSource)
- _private->firstLayoutDone = YES;
- }
-}
-
// Called after we send an openURL:... down to WebCore.
- (void)_opened
{
}
}
-- (void)_clearProvisionalLoad
-{
- [self _setProvisionalDataSource:nil];
- [[self webView] _progressCompleted:self];
- [self _setState:WebFrameStateComplete];
-}
-
-- (void)_markLoadComplete
-{
- [self _setState:WebFrameStateComplete];
-}
-
- (void)_checkLoadCompleteForThisFrame
{
ASSERT([self webView] != nil);
- switch ([self _state]) {
+ switch ([_private->frameLoader state]) {
case WebFrameStateProvisional:
{
if (_private->delegateIsHandlingProvisionalLoadError)
// Finish resetting the load state, but only if another load hasn't been started by the
// delegate callback.
- if (pd == _private->provisionalDataSource) {
- [self _clearProvisionalLoad];
- } else {
- NSURL *unreachableURL = [_private->provisionalDataSource unreachableURL];
+ if (pd == [_private->frameLoader provisionalDataSource])
+ [_private->frameLoader clearProvisionalLoad];
+ else {
+ NSURL *unreachableURL = [[_private->frameLoader provisionalDataSource] unreachableURL];
if (unreachableURL != nil && [unreachableURL isEqual:[[pd request] URL]]) {
shouldReset = NO;
}
NSView <WebDocumentView> *thisDocumentView = [thisView documentView];
ASSERT(thisDocumentView != nil);
- [self _markLoadComplete];
+ [_private->frameLoader markLoadComplete];
// FIXME: Is this subsequent work important if we already navigated away?
// Maybe there are bugs because of that, or extra work we can skip because
_private->delegateIsHandlingUnimplementablePolicy = NO;
}
-- (void)_clearProvisionalDataSource
-{
- [self _setProvisionalDataSource:nil];
-}
-
// helper method that determines whether the subframes described by the item's subitems
// match our own current frameset
- (BOOL)_childFramesMatchItem:(WebHistoryItem *)item
// We always call scrollToAnchorWithURL here, even if the URL doesn't have an
// anchor fragment. This is so we'll keep the WebCore Frame's URL up-to-date.
- [[_private->dataSource _bridge] scrollToAnchorWithURL:[item URL]];
+ [_private->bridge scrollToAnchorWithURL:[item URL]];
// must do this maintenance here, since we don't go through a real page reload
[_private setCurrentItem:item];
[_private->listener release];
_private->listener = nil;
}
- [_private->provisionalDataSource _startLoading];
-}
-
-- (void)_startProvisionalLoad:(WebDataSource *)dataSource
-{
- [self _setProvisionalDataSource:dataSource];
- [self _setState:WebFrameStateProvisional];
+ [_private->frameLoader startLoading];
}
-(void)_continueLoadRequestAfterNavigationPolicy:(NSURLRequest *)request formState:(WebFormState *)formState
[self stopLoading];
[self _setLoadType:loadType];
- [self _startProvisionalLoad:dataSource];
+ [_private->frameLoader startProvisionalLoad:dataSource];
[dataSource release];
[self _setPolicyDataSource:nil];
NSDictionary *pageCache = [[_private provisionalItem] pageCache];
if ([pageCache objectForKey:WebCorePageCacheStateKey]){
LOG (PageCache, "Restoring page from back/forward cache, %@\n", [[_private provisionalItem] URL]);
- [_private->provisionalDataSource _loadFromPageCache:pageCache];
+ [[_private->frameLoader provisionalDataSource] _loadFromPageCache:pageCache];
return;
}
}
withSelector:@selector(_continueLoadRequestAfterNavigationPolicy:formState:)];
}
-- (void)_setProvisionalDataSource: (WebDataSource *)d
-{
- if (_private->provisionalDataSource != _private->dataSource) {
- [_private->provisionalDataSource _setWebFrame:nil];
- }
- [_private setProvisionalDataSource: d];
- [d _setWebFrame:self];
-}
-
// used to decide to use loadType=Same
- (BOOL)_shouldTreatURLAsSameAsCurrent:(NSURL *)URL
{
[fv _setWebFrame:self];
}
+ _private->frameLoader = [[WebFrameLoader alloc] initWithWebFrame:self];
+
++WebFrameCount;
return self;
_private->firstLayoutDone = YES;
}
-- (void)_setupForReplace
-{
- [self _setState:WebFrameStateProvisional];
- WebDataSource *old = _private->provisionalDataSource;
- _private->provisionalDataSource = _private->dataSource;
- _private->dataSource = nil;
- [old release];
-
- [self _detachChildren];
-}
- (BOOL)_hasSelection
{
[_private->inspectors removeObject:inspector];
}
+- (WebFrameLoader *)_frameLoader
+{
+ return _private->frameLoader;
+}
+
+- (void)_provisionalLoadStarted
+{
+ _private->firstLayoutDone = NO;
+ [_private->bridge provisionalLoadStarted];
+
+ // FIXME: This is OK as long as no one resizes the window,
+ // but in the case where someone does, it means garbage outside
+ // the occupied part of the scroll view.
+ [[[self frameView] _scrollView] setDrawsBackground:NO];
+
+ // Cache the page, if possible.
+ // Don't write to the cache if in the middle of a redirect, since we will want to
+ // store the final page we end up on.
+ // No point writing to the cache on a reload or loadSame, since we will just write
+ // over it again when we leave that page.
+ WebHistoryItem *item = [_private currentItem];
+ WebFrameLoadType loadType = [self _loadType];
+ if ([self _canCachePage]
+ && [_private->bridge canCachePage]
+ && item
+ && !_private->quickRedirectComing
+ && loadType != WebFrameLoadTypeReload
+ && loadType != WebFrameLoadTypeReloadAllowingStaleData
+ && loadType != WebFrameLoadTypeSame
+ && ![[self dataSource] isLoading]
+ && ![[self dataSource] _isStopping]) {
+ if ([[[self dataSource] representation] isKindOfClass: [WebHTMLRepresentation class]]) {
+ if (![item pageCache]){
+
+ // Add the items to this page's cache.
+ if ([self _createPageCacheForItem:item]) {
+ LOG(PageCache, "Saving page to back/forward cache, %@\n", [[self dataSource] _URL]);
+
+ // See if any page caches need to be purged after the addition of this
+ // new page cache.
+ [self _purgePageCache];
+ }
+ else
+ LOG(PageCache, "NOT saving page to back/forward cache, unable to create items, %@\n", [[self dataSource] _URL]);
+ }
+ } else
+ // Put the document into a null state, so it can be restored correctly.
+ [_private->bridge clear];
+ } else
+ LOG(PageCache, "NOT saving page to back/forward cache, %@\n", [[self dataSource] _URL]);
+}
+
+- (void)_prepareForDataSourceReplacement
+{
+ if (![_private->frameLoader dataSource]) {
+ ASSERT(![self _childFrameCount]);
+ return;
+ }
+
+ // Make sure that any work that is triggered by resigning first reponder can get done.
+ // The main example where this came up is the textDidEndEditing that is sent to the
+ // FormsDelegate (3223413). We need to do this before _detachChildren, since that will
+ // remove the views as a side-effect of freeing the bridge, at which point we can't
+ // post the FormDelegate messages.
+ //
+ // Note that this can also take FirstResponder away from a child of our frameView that
+ // is not in a child frame's view. This is OK because we are in the process
+ // of loading new content, which will blow away all editors in this top frame, and if
+ // a non-editor is firstReponder it will not be affected by endEditingFor:.
+ // Potentially one day someone could write a DocView whose editors were not all
+ // replaced by loading new content, but that does not apply currently.
+ NSView *frameView = [self frameView];
+ NSWindow *window = [frameView window];
+ NSResponder *firstResp = [window firstResponder];
+ if ([firstResp isKindOfClass:[NSView class]]
+ && [(NSView *)firstResp isDescendantOf:frameView])
+ {
+ [window endEditingFor:firstResp];
+ }
+
+ [self _detachChildren];
+}
+
+- (void)_frameLoadCompleted
+{
+ NSScrollView *sv = [[self frameView] _scrollView];
+ if ([[self webView] drawsBackground])
+ [sv setDrawsBackground:YES];
+ [_private setPreviousItem:nil];
+ // After a canceled provisional load, firstLayoutDone is NO. Reset it to YES if we're displaying a page.
+ if ([_private->frameLoader dataSource])
+ _private->firstLayoutDone = YES;
+}
+
@end
@implementation WebFormState : NSObject
- (WebDataSource *)provisionalDataSource
{
- return [_private provisionalDataSource];
+ return [_private->frameLoader provisionalDataSource];
}
- (WebDataSource *)dataSource
{
- return [_private dataSource];
+ return [_private->frameLoader dataSource];
}
- (void)loadRequest:(NSURLRequest *)request
[self _invalidatePendingPolicyDecisionCallingDefaultAction:YES];
[self _stopLoadingSubframes];
- [_private->provisionalDataSource _stopLoading];
- [_private->dataSource _stopLoading];
-
- [self _clearProvisionalDataSource];
+ [_private->frameLoader stopLoading];
_private->isStoppingLoad = NO;
}
#import <WebKit/WebFrameLoader.h>
#import <JavaScriptCore/Assertions.h>
-#import <WebKit/WebDataSource.h>
+#import <WebKit/WebDataSourceInternal.h>
#import <WebKit/WebFrameInternal.h>
#import <WebKit/WebIconLoader.h>
#import <WebKit/WebMainResourceLoader.h>
+#import <WebKit/WebKitLogging.h>
+#import <WebKit/WebViewInternal.h>
@implementation WebFrameLoader
-- (id)initWithDataSource:(WebDataSource *)ds
+- (id)initWithWebFrame:(WebFrame *)wf
{
self = [super init];
- if (self)
- dataSource = ds;
+ if (self) {
+ webFrame = wf;
+ state = WebFrameStateCommittedPage;
+ }
return self;
}
[subresourceLoaders release];
[plugInStreamLoaders release];
[iconLoader release];
+ [dataSource release];
+ [provisionalDataSource release];
+
[super dealloc];
}
- (BOOL)startLoadingMainResourceWithRequest:(NSMutableURLRequest *)request identifier:(id)identifier
{
- mainResourceLoader = [[WebMainResourceLoader alloc] initWithDataSource:dataSource];
+ mainResourceLoader = [[WebMainResourceLoader alloc] initWithDataSource:provisionalDataSource];
[mainResourceLoader setIdentifier:identifier];
- [[dataSource webFrame] _addExtraFieldsToRequest:request mainResource:YES alwaysFromRequest:NO];
+ [[provisionalDataSource webFrame] _addExtraFieldsToRequest:request mainResource:YES alwaysFromRequest:NO];
if (![mainResourceLoader loadWithRequest:request]) {
// FIXME: if this should really be caught, we should just ASSERT this doesn't happen;
// should it be caught by other parts of WebKit or other parts of the app?
[mainResourceLoader cancelWithError:error];
}
+- (WebDataSource *)dataSource
+{
+ return dataSource;
+}
+
+- (void)_setDataSource:(WebDataSource *)ds
+{
+ if (ds == nil && dataSource == nil)
+ return;
+
+ ASSERT(ds != dataSource);
+
+ [webFrame _prepareForDataSourceReplacement];
+ [dataSource _setWebFrame:nil];
+
+ [ds retain];
+ [dataSource release];
+ dataSource = ds;
+
+ [ds _setWebFrame:webFrame];
+}
+
+- (void)clearDataSource
+{
+ [self _setDataSource:nil];
+}
+
+- (WebDataSource *)provisionalDataSource
+{
+ return provisionalDataSource;
+}
+
+- (void)_setProvisionalDataSource: (WebDataSource *)d
+{
+ ASSERT(!d || !provisionalDataSource);
+
+ if (provisionalDataSource != dataSource)
+ [provisionalDataSource _setWebFrame:nil];
+
+ [d retain];
+ [provisionalDataSource release];
+ provisionalDataSource = d;
+
+ [d _setWebFrame:webFrame];
+}
+
+- (void)_clearProvisionalDataSource
+{
+ [self _setProvisionalDataSource:nil];
+}
+
+- (WebFrameState)state
+{
+ return state;
+}
+
+#ifndef NDEBUG
+static const char * const stateNames[] = {
+ "WebFrameStateProvisional",
+ "WebFrameStateCommittedPage",
+ "WebFrameStateComplete"
+};
+#endif
+
+static CFAbsoluteTime _timeOfLastCompletedLoad;
+
++ (CFAbsoluteTime)timeOfLastCompletedLoad
+{
+ return _timeOfLastCompletedLoad;
+}
+
+- (void)_setState:(WebFrameState)newState
+{
+ LOG(Loading, "%@: transition from %s to %s", [webFrame name], stateNames[state], stateNames[newState]);
+ if ([webFrame webView])
+ LOG(Timing, "%@: transition from %s to %s, %f seconds since start of document load", [webFrame name], stateNames[state], stateNames[newState], CFAbsoluteTimeGetCurrent() - [[[[webFrame webView] mainFrame] dataSource] _loadingStartedTime]);
+
+ if (newState == WebFrameStateComplete && webFrame == [[webFrame webView] mainFrame])
+ LOG(DocumentLoad, "completed %@ (%f seconds)", [[[self dataSource] request] URL], CFAbsoluteTimeGetCurrent() - [[self dataSource] _loadingStartedTime]);
+
+ state = newState;
+
+ if (state == WebFrameStateProvisional)
+ [webFrame _provisionalLoadStarted];
+ else if (state == WebFrameStateComplete) {
+ [webFrame _frameLoadCompleted];
+ _timeOfLastCompletedLoad = CFAbsoluteTimeGetCurrent();
+ [dataSource _stopRecordingResponses];
+ }
+}
+
+- (void)clearProvisionalLoad
+{
+ [self _setProvisionalDataSource:nil];
+ [[webFrame webView] _progressCompleted:webFrame];
+ [self _setState:WebFrameStateComplete];
+}
+
+- (void)markLoadComplete
+{
+ [self _setState:WebFrameStateComplete];
+}
+
+- (void)commitProvisionalLoad
+{
+ [self stopLoadingSubresources];
+ [self stopLoadingPlugIns];
+
+ [self _setDataSource:provisionalDataSource];
+ [self _setProvisionalDataSource:nil];
+ [self _setState:WebFrameStateCommittedPage];
+}
+
+- (void)stopLoading
+{
+ [provisionalDataSource _stopLoading];
+ [dataSource _stopLoading];
+ [self _clearProvisionalDataSource];
+}
+
+// FIXME: poor method name; also why is this not part of startProvisionalLoad:?
+- (void)startLoading
+{
+ [provisionalDataSource _startLoading];
+}
+
+- (void)startProvisionalLoad:(WebDataSource *)ds
+{
+ [self _setProvisionalDataSource:ds];
+ [self _setState:WebFrameStateProvisional];
+}
+
+- (void)setupForReplace
+{
+ [self _setState:WebFrameStateProvisional];
+ WebDataSource *old = provisionalDataSource;
+ provisionalDataSource = dataSource;
+ dataSource = nil;
+ [old release];
+
+ [webFrame _detachChildren];
+}
+
@end