From e88d8440a54b7615bef349fff338345b760ac5d3 Mon Sep 17 00:00:00 2001 From: mjs Date: Thu, 24 Aug 2006 01:28:20 +0000 Subject: [PATCH] Reviewed by Adele. - refactoring of WebDataSource in preparation for moving a bunch of it to a new class - minimize WebDataSourceInternal.h to be only methods called from outside WebDataSource - reduce Private category implementation to be only the SPI methods - make new Internal and FileInternal categories which contain the remainder (depending on whether they are called from outside of WebDataSource) * WebView/WebDataSource.m: (-[WebDataSource _setMainDocumentError:]): (addTypesFromClass): (+[WebDataSource _representationClassForMIMEType:]): (-[WebDataSource _commitIfReady]): (-[WebDataSource _commitLoadWithData:]): (-[WebDataSource _doesProgressiveLoadWithMIMEType:]): (-[WebDataSource _addResponse:]): (-[WebDataSource _revertToProvisionalState]): (-[WebDataSource _mainDocumentError]): (-[WebDataSource _addSubframeArchives:]): (-[WebDataSource _fileWrapperForURL:]): (+[WebDataSource _repTypesAllowImageTypeOmission:]): (-[WebDataSource _decidePolicyForMIMEType:decisionListener:]): (-[WebDataSource _finishedLoading]): (-[WebDataSource _setResponse:]): (-[WebDataSource _setRequest:]): (-[WebDataSource _setupForReplaceByMIMEType:]): (-[WebDataSource _receivedMainResourceError:complete:]): (-[WebDataSource _mainReceivedError:complete:]): (-[WebDataSource _defersCallbacks]): (-[WebDataSource _downloadWithLoadingConnection:request:response:proxy:]): (-[WebDataSource _didFailLoadingWithError:forResource:]): (-[WebDataSource _didFinishLoadingForResource:]): (-[WebDataSource _didReceiveData:contentLength:forResource:]): (-[WebDataSource _didReceiveResponse:forResource:]): (-[WebDataSource _didCancelAuthenticationChallenge:forResource:]): (-[WebDataSource _didReceiveAuthenticationChallenge:forResource:]): (-[WebDataSource _willSendRequest:forResource:redirectResponse:]): (-[WebDataSource _identifierForInitialRequest:]): (-[WebDataSource _archivedSubresourceForURL:]): (-[WebDataSource _startLoading]): (-[WebDataSource _stopRecordingResponses]): (-[WebDataSource _loadingStartedTime]): (-[WebDataSource _replaceSelectionWithArchive:selectReplacement:]): (-[WebDataSource _documentFragmentWithArchive:]): (-[WebDataSource _documentFragmentWithImageResource:]): (-[WebDataSource _imageElementWithImageResource:]): (-[WebDataSource _title]): (-[WebDataSource _isStopping]): (-[WebDataSource _setWebFrame:]): (-[WebDataSource _URL]): (-[WebDataSource _loadFromPageCache:]): (-[WebDataSource _popSubframeArchiveWithName:]): (-[WebDataSource _setIsClientRedirect:]): (-[WebDataSource _setURL:]): (-[WebDataSource _setLastCheckedRequest:]): (-[WebDataSource _defersCallbacksChanged]): (-[WebDataSource _lastCheckedRequest]): (-[WebDataSource _stopLoading]): (-[WebDataSource _bridge]): (-[WebDataSource _webView]): (-[WebDataSource _triggeringAction]): (-[WebDataSource _setTriggeringAction:]): (-[WebDataSource __adoptRequest:]): (-[WebDataSource _isDocumentHTML]): (-[WebDataSource _stopLoadingWithError:]): (-[WebDataSource _setPrimaryLoadComplete:]): (-[WebDataSource _responses]): (-[WebDataSource _makeRepresentation]): (-[WebDataSource _isClientRedirect]): (-[WebDataSource _originalRequest]): (-[WebDataSource _URLForHistory]): (-[WebDataSource _addToUnarchiveState:]): (-[WebDataSource _setOverrideEncoding:]): (-[WebDataSource _setIconURL:]): (-[WebDataSource _setIconURL:withType:]): (-[WebDataSource _overrideEncoding]): (-[WebDataSource _setTitle:]): * WebView/WebDataSourceInternal.h: git-svn-id: https://svn.webkit.org/repository/webkit/trunk@16003 268f45cc-cd09-0410-ab3c-d52691b4dbfc --- WebKit/ChangeLog | 83 ++ WebKit/WebView/WebDataSource.m | 1100 ++++++++++++------------ WebKit/WebView/WebDataSourceInternal.h | 68 +- 3 files changed, 673 insertions(+), 578 deletions(-) diff --git a/WebKit/ChangeLog b/WebKit/ChangeLog index 118a0ff5cfd2..d8782aee9ede 100644 --- a/WebKit/ChangeLog +++ b/WebKit/ChangeLog @@ -1,3 +1,86 @@ +2006-08-23 Maciej Stachowiak + + Reviewed by Adele. + + - refactoring of WebDataSource in preparation for moving a bunch of it to a new class + + - minimize WebDataSourceInternal.h to be only methods called from outside WebDataSource + - reduce Private category implementation to be only the SPI methods + - make new Internal and FileInternal categories which contain the + remainder (depending on whether they are called from outside of + WebDataSource) + + * WebView/WebDataSource.m: + (-[WebDataSource _setMainDocumentError:]): + (addTypesFromClass): + (+[WebDataSource _representationClassForMIMEType:]): + (-[WebDataSource _commitIfReady]): + (-[WebDataSource _commitLoadWithData:]): + (-[WebDataSource _doesProgressiveLoadWithMIMEType:]): + (-[WebDataSource _addResponse:]): + (-[WebDataSource _revertToProvisionalState]): + (-[WebDataSource _mainDocumentError]): + (-[WebDataSource _addSubframeArchives:]): + (-[WebDataSource _fileWrapperForURL:]): + (+[WebDataSource _repTypesAllowImageTypeOmission:]): + (-[WebDataSource _decidePolicyForMIMEType:decisionListener:]): + (-[WebDataSource _finishedLoading]): + (-[WebDataSource _setResponse:]): + (-[WebDataSource _setRequest:]): + (-[WebDataSource _setupForReplaceByMIMEType:]): + (-[WebDataSource _receivedMainResourceError:complete:]): + (-[WebDataSource _mainReceivedError:complete:]): + (-[WebDataSource _defersCallbacks]): + (-[WebDataSource _downloadWithLoadingConnection:request:response:proxy:]): + (-[WebDataSource _didFailLoadingWithError:forResource:]): + (-[WebDataSource _didFinishLoadingForResource:]): + (-[WebDataSource _didReceiveData:contentLength:forResource:]): + (-[WebDataSource _didReceiveResponse:forResource:]): + (-[WebDataSource _didCancelAuthenticationChallenge:forResource:]): + (-[WebDataSource _didReceiveAuthenticationChallenge:forResource:]): + (-[WebDataSource _willSendRequest:forResource:redirectResponse:]): + (-[WebDataSource _identifierForInitialRequest:]): + (-[WebDataSource _archivedSubresourceForURL:]): + (-[WebDataSource _startLoading]): + (-[WebDataSource _stopRecordingResponses]): + (-[WebDataSource _loadingStartedTime]): + (-[WebDataSource _replaceSelectionWithArchive:selectReplacement:]): + (-[WebDataSource _documentFragmentWithArchive:]): + (-[WebDataSource _documentFragmentWithImageResource:]): + (-[WebDataSource _imageElementWithImageResource:]): + (-[WebDataSource _title]): + (-[WebDataSource _isStopping]): + (-[WebDataSource _setWebFrame:]): + (-[WebDataSource _URL]): + (-[WebDataSource _loadFromPageCache:]): + (-[WebDataSource _popSubframeArchiveWithName:]): + (-[WebDataSource _setIsClientRedirect:]): + (-[WebDataSource _setURL:]): + (-[WebDataSource _setLastCheckedRequest:]): + (-[WebDataSource _defersCallbacksChanged]): + (-[WebDataSource _lastCheckedRequest]): + (-[WebDataSource _stopLoading]): + (-[WebDataSource _bridge]): + (-[WebDataSource _webView]): + (-[WebDataSource _triggeringAction]): + (-[WebDataSource _setTriggeringAction:]): + (-[WebDataSource __adoptRequest:]): + (-[WebDataSource _isDocumentHTML]): + (-[WebDataSource _stopLoadingWithError:]): + (-[WebDataSource _setPrimaryLoadComplete:]): + (-[WebDataSource _responses]): + (-[WebDataSource _makeRepresentation]): + (-[WebDataSource _isClientRedirect]): + (-[WebDataSource _originalRequest]): + (-[WebDataSource _URLForHistory]): + (-[WebDataSource _addToUnarchiveState:]): + (-[WebDataSource _setOverrideEncoding:]): + (-[WebDataSource _setIconURL:]): + (-[WebDataSource _setIconURL:withType:]): + (-[WebDataSource _overrideEncoding]): + (-[WebDataSource _setTitle:]): + * WebView/WebDataSourceInternal.h: + 2006-08-23 Brady Eidson Reviewed by John Sullivan diff --git a/WebKit/WebView/WebDataSource.m b/WebKit/WebView/WebDataSource.m index dab9c22361fd..20c712b5eed8 100644 --- a/WebKit/WebView/WebDataSource.m +++ b/WebKit/WebView/WebDataSource.m @@ -169,108 +169,10 @@ @end -@implementation WebDataSource (WebPrivate) - -- (NSFileWrapper *)_fileWrapperForURL:(NSURL *)URL -{ - if ([URL isFileURL]) { - NSString *path = [[URL path] stringByResolvingSymlinksInPath]; - return [[[NSFileWrapper alloc] initWithPath:path] autorelease]; - } - - WebResource *resource = [self subresourceForURL:URL]; - if (resource) { - return [resource _fileWrapperRepresentation]; - } - - NSCachedURLResponse *cachedResponse = [[self _webView] _cachedResponseForURL:URL]; - if (cachedResponse) { - NSFileWrapper *wrapper = [[[NSFileWrapper alloc] initRegularFileWithContents:[cachedResponse data]] autorelease]; - [wrapper setPreferredFilename:[[cachedResponse response] suggestedFilename]]; - return wrapper; - } - - return nil; -} - -- (void)_addSubframeArchives:(NSArray *)subframeArchives -{ - NSEnumerator *enumerator = [subframeArchives objectEnumerator]; - WebArchive *archive; - while ((archive = [enumerator nextObject]) != nil) - [self _addToUnarchiveState:archive]; -} - -- (void)_addToUnarchiveState:(WebArchive *)archive -{ - if (!_private->unarchivingState) - _private->unarchivingState = [[WebUnarchivingState alloc] init]; - [_private->unarchivingState addArchive:archive]; -} - -- (WebArchive *)_popSubframeArchiveWithName:(NSString *)frameName -{ - return [_private->unarchivingState popSubframeArchiveWithFrameName:frameName]; -} - -- (DOMElement *)_imageElementWithImageResource:(WebResource *)resource -{ - if (!resource) - return 0; - - [self addSubresource:resource]; - - DOMElement *imageElement = [[[self _bridge] DOMDocument] createElement:@"img"]; - - // FIXME: calling _web_originalDataAsString on a file URL returns an absolute path. Workaround this. - NSURL *URL = [resource URL]; - [imageElement setAttribute:@"src" :[URL isFileURL] ? [URL absoluteString] : [URL _web_originalDataAsString]]; - - return imageElement; -} - -- (DOMDocumentFragment *)_documentFragmentWithImageResource:(WebResource *)resource -{ - DOMElement *imageElement = [self _imageElementWithImageResource:resource]; - if (!imageElement) - return 0; - DOMDocumentFragment *fragment = [[[self _bridge] DOMDocument] createDocumentFragment]; - [fragment appendChild:imageElement]; - return fragment; -} - -- (DOMDocumentFragment *)_documentFragmentWithArchive:(WebArchive *)archive -{ - ASSERT(archive); - WebResource *mainResource = [archive mainResource]; - if (mainResource) { - NSString *MIMEType = [mainResource MIMEType]; - if ([WebView canShowMIMETypeAsHTML:MIMEType]) { - NSString *markupString = [[NSString alloc] initWithData:[mainResource data] encoding:NSUTF8StringEncoding]; - // FIXME: seems poor form to do this as a side effect of getting a document fragment - [self _addToUnarchiveState:archive]; - DOMDocumentFragment *fragment = [[self _bridge] documentFragmentWithMarkupString:markupString baseURLString:[[mainResource URL] _web_originalDataAsString]]; - [markupString release]; - return fragment; - } else if ([[WebFrameBridge supportedImageResourceMIMETypes] containsObject:MIMEType]) { - return [self _documentFragmentWithImageResource:mainResource]; - - } - } - return nil; -} - -- (void)_replaceSelectionWithArchive:(WebArchive *)archive selectReplacement:(BOOL)selectReplacement -{ - DOMDocumentFragment *fragment = [self _documentFragmentWithArchive:archive]; - if (fragment) - [[self _bridge] replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:NO matchStyle:NO]; -} +@interface WebDataSource (WebFileInternal) +@end -- (WebView *)_webView -{ - return [_private->webFrame webView]; -} +@implementation WebDataSource (WebFileInternal) - (void)_setRepresentation: (id)representation { @@ -322,26 +224,6 @@ } } -- (void)_setPrimaryLoadComplete:(BOOL)flag -{ - _private->primaryLoadComplete = flag; - - if (flag) { - // FIXME: We could actually load it as soon as we've parsed - // the HEAD section, or determined there isn't one - but - // there's no callback for that. - [self _loadIcon]; - - if ([[_private->webFrame _frameLoader] isLoadingMainResource]) { - [self _setData:[[_private->webFrame _frameLoader] mainResourceData]]; - [[_private->webFrame _frameLoader] releaseMainResourceLoader]; - } - - if ([WebScriptDebugServer listenerCount]) - [[WebScriptDebugServer sharedScriptDebugServer] webView:[[self webFrame] webView] didLoadMainResourceForDataSource:self]; - } -} - - (NSError *)_cancelledError { return [NSError _webKitErrorWithDomain:NSURLErrorDomain @@ -349,46 +231,16 @@ URL:[self _URL]]; } -// Cancels the data source's pending loads. Conceptually, a data source only loads -// one document at a time, but one document may have many related resources. -// _stopLoading will stop all loads initiated by the data source, -// but not loads initiated by child frames' data sources -- that's the WebFrame's job. -- (void)_stopLoading +- (void)_setMainDocumentError: (NSError *)error { - // 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->webFrame _frameLoader] stopLoadingIcon]; - - // The same goes for the bridge/part, which may still be parsing. - if (_private->committed) - [[self _bridge] stopLoading]; - - if (![[_private->webFrame _frameLoader] isLoading]) - return; - - [self retain]; - - _private->stopping = YES; + [error retain]; + [_private->mainDocumentError release]; + _private->mainDocumentError = error; - if ([[_private->webFrame _frameLoader] isLoadingMainResource]) { - // Stop the main resource loader and let it send the cancelled message. - [[_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]]; - } else { - // If there are no resource loaders, we need to manufacture a cancelled message. - // (A back/forward navigation has no resource loaders because its resources are cached.) - [self _mainReceivedError:[self _cancelledError] complete:YES]; + if (!_private->representationFinishedLoading) { + _private->representationFinishedLoading = YES; + [[self representation] receivedError:error withDataSource:self]; } - - [[_private->webFrame _frameLoader] stopLoadingSubresources]; - [[_private->webFrame _frameLoader] stopLoadingPlugIns]; - - _private->stopping = NO; - - [self release]; } - (void)_clearErrors @@ -413,209 +265,106 @@ didStartProvisionalLoadForFrame:[self webFrame]]; } -- (void)_loadFromPageCache:(NSDictionary *)pageCache +static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class class, NSArray *supportTypes) { - [self _prepareForLoadStart]; - _private->loadingFromPageCache = YES; - _private->committed = TRUE; - [[self webFrame] _commitProvisionalLoad:pageCache]; + NSEnumerator *enumerator = [supportTypes objectEnumerator]; + ASSERT(enumerator != nil); + NSString *mime = nil; + while ((mime = [enumerator nextObject]) != nil) { + // Don't clobber previously-registered classes. + if ([allTypes objectForKey:mime] == nil) + [allTypes setObject:class forKey:mime]; + } } -- (void)_startLoading ++ (Class)_representationClassForMIMEType:(NSString *)MIMEType { - [self _prepareForLoadStart]; - - if ([[_private->webFrame _frameLoader] isLoadingMainResource]) - return; + Class repClass; + return [WebView _viewClass:nil andRepresentationClass:&repClass forMIMEType:MIMEType] ? repClass : nil; +} - _private->loadingFromPageCache = NO; - - id identifier; - id resourceLoadDelegate = [[self _webView] resourceLoadDelegate]; - if ([resourceLoadDelegate respondsToSelector:@selector(webView:identifierForInitialRequest:fromDataSource:)]) - identifier = [resourceLoadDelegate webView:[self _webView] identifierForInitialRequest:_private->originalRequest fromDataSource:self]; - else - identifier = [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:[self _webView] identifierForInitialRequest:_private->originalRequest fromDataSource:self]; - - [[_private->webFrame _frameLoader] startLoadingMainResourceWithRequest:_private->request identifier:identifier]; +- (void)_commitIfReady +{ + if (_private->gotFirstByte && !_private->committed) { + _private->committed = TRUE; + [[self webFrame] _commitProvisionalLoad:nil]; + } } -- (BOOL)_isStopping +- (void)_commitLoadWithData:(NSData *)data { - return _private->stopping; + // Both unloading the old page and parsing the new page may execute JavaScript which destroys the datasource + // by starting a new load, so retain temporarily. + [self retain]; + [self _commitIfReady]; + [[self representation] receivedData:data withDataSource:self]; + [[[[self webFrame] frameView] documentView] dataSourceUpdated:self]; + [self release]; } -- (double)_loadingStartedTime +- (BOOL)_doesProgressiveLoadWithMIMEType:(NSString *)MIMEType { - return _private->loadingStartedTime; + return [[self webFrame] _loadType] != WebFrameLoadTypeReplace || [MIMEType isEqualToString:@"text/html"]; } -- (NSURL *)_URLForHistory +- (void)_addResponse:(NSURLResponse *)r { - // Return the URL to be used for history and B/F list. - // Returns nil for WebDataProtocol URLs that aren't alternates - // for unreachable URLs, because these can't be stored in history. - NSURL *URL = [_private->originalRequestCopy URL]; - if ([WebDataProtocol _webIsDataProtocolURL:URL]) { - URL = [_private->originalRequestCopy _webDataRequestUnreachableURL]; + if (!_private->stopRecordingResponses) { + if (!_private->responses) + _private->responses = [[NSMutableArray alloc] init]; + [_private->responses addObject: r]; } - - return [URL _webkit_canonicalize]; } -- (void)_setTitle:(NSString *)title +- (void)_revertToProvisionalState { - NSString *trimmed; - if (title == nil) { - trimmed = nil; - } else { - trimmed = [title _webkit_stringByTrimmingWhitespace]; - if ([trimmed length] == 0) - trimmed = nil; - } - if (trimmed == nil) { - if (_private->pageTitle == nil) - return; - } else { - if ([_private->pageTitle isEqualToString:trimmed]) - return; - } - - if (!trimmed || [trimmed length] == 0) - return; - - [[self _webView] _willChangeValueForKey:_WebMainFrameTitleKey]; - [_private->pageTitle release]; - _private->pageTitle = [trimmed copy]; - [[self _webView] _didChangeValueForKey:_WebMainFrameTitleKey]; - - // The title doesn't get communicated to the WebView until we are committed. - if (_private->committed) { - NSURL *URLForHistory = [self _URLForHistory]; - if (URLForHistory != nil) { - WebHistoryItem *entry = [[WebHistory optionalSharedHistory] itemForURL:URLForHistory]; - [entry setTitle: _private->pageTitle]; - - // Must update the entries in the back-forward list too. This must go through the WebFrame because - // it has the right notion of the current b/f item. - [[self webFrame] _setTitle:_private->pageTitle]; - - [[self _webView] setMainFrameDocumentReady:YES]; // update observers with new DOMDocument - [[[self _webView] _frameLoadDelegateForwarder] webView:[self _webView] - didReceiveTitle:_private->pageTitle - forFrame:[self webFrame]]; - } - } + [self _setRepresentation:nil]; + [[_private->webFrame _frameLoader] setupForReplace]; + _private->committed = NO; } -- (NSString *)_title -{ - return _private->pageTitle; -} +@end -- (void)_setURL:(NSURL *)URL -{ - NSMutableURLRequest *newOriginalRequest = [_private->originalRequestCopy mutableCopy]; - [_private->originalRequestCopy release]; - [newOriginalRequest setURL:URL]; - _private->originalRequestCopy = newOriginalRequest; +@implementation WebDataSource (WebPrivate) - NSMutableURLRequest *newRequest = [_private->request mutableCopy]; - [_private->request release]; - [newRequest setURL:URL]; - _private->request = newRequest; +- (NSError *)_mainDocumentError +{ + return _private->mainDocumentError; } -- (void)__adoptRequest:(NSMutableURLRequest *)request +- (void)_addSubframeArchives:(NSArray *)subframeArchives { - if (request != _private->request){ - [_private->request release]; - _private->request = [request retain]; - } + NSEnumerator *enumerator = [subframeArchives objectEnumerator]; + WebArchive *archive; + while ((archive = [enumerator nextObject]) != nil) + [self _addToUnarchiveState:archive]; } -- (void)_setRequest:(NSURLRequest *)request +- (NSFileWrapper *)_fileWrapperForURL:(NSURL *)URL { - ASSERT_ARG(request, request != _private->request); + if ([URL isFileURL]) { + NSString *path = [[URL path] stringByResolvingSymlinksInPath]; + return [[[NSFileWrapper alloc] initWithPath:path] autorelease]; + } - // Replacing an unreachable URL with alternate content looks like a server-side - // redirect at this point, but we can replace a committed dataSource. - BOOL handlingUnreachableURL = [request _webDataRequestUnreachableURL] != nil; - if (handlingUnreachableURL) { - _private->committed = NO; + WebResource *resource = [self subresourceForURL:URL]; + if (resource) { + return [resource _fileWrapperRepresentation]; } - // We should never be getting a redirect callback after the data - // source is committed, except in the unreachable URL case. It - // would be a WebFoundation bug if it sent a redirect callback after commit. - ASSERT(!_private->committed); - - NSURLRequest *oldRequest = _private->request; - - _private->request = [request mutableCopy]; - - // Only send webView:didReceiveServerRedirectForProvisionalLoadForFrame: if URL changed. - // Also, don't send it when replacing unreachable URLs with alternate content. - if (!handlingUnreachableURL && ![[oldRequest URL] isEqual: [request URL]]) { - LOG(Redirect, "Server redirect to: %@", [request URL]); - [[[self _webView] _frameLoadDelegateForwarder] webView:[self _webView] - didReceiveServerRedirectForProvisionalLoadForFrame:[self webFrame]]; + NSCachedURLResponse *cachedResponse = [[self _webView] _cachedResponseForURL:URL]; + if (cachedResponse) { + NSFileWrapper *wrapper = [[[NSFileWrapper alloc] initRegularFileWithContents:[cachedResponse data]] autorelease]; + [wrapper setPreferredFilename:[[cachedResponse response] suggestedFilename]]; + return wrapper; } - - [oldRequest release]; -} - -- (void)_setResponse:(NSURLResponse *)response -{ - [_private->response release]; - _private->response = [response retain]; -} - -- (void)_setOverrideEncoding:(NSString *)overrideEncoding -{ - NSString *copy = [overrideEncoding copy]; - [_private->overrideEncoding release]; - _private->overrideEncoding = copy; -} - -- (NSString *)_overrideEncoding -{ - return [[_private->overrideEncoding copy] autorelease]; -} - -- (void)_setIsClientRedirect:(BOOL)flag -{ - _private->isClientRedirect = flag; -} - -- (BOOL)_isClientRedirect -{ - return _private->isClientRedirect; + + return nil; } -- (void)_setMainDocumentError: (NSError *)error -{ - [error retain]; - [_private->mainDocumentError release]; - _private->mainDocumentError = error; - - if (!_private->representationFinishedLoading) { - _private->representationFinishedLoading = YES; - [[self representation] receivedError:error withDataSource:self]; - } -} +@end -static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class class, NSArray *supportTypes) -{ - NSEnumerator *enumerator = [supportTypes objectEnumerator]; - ASSERT(enumerator != nil); - NSString *mime = nil; - while ((mime = [enumerator nextObject]) != nil) { - // Don't clobber previously-registered classes. - if ([allTypes objectForKey:mime] == nil) - [allTypes setObject:class forKey:mime]; - } -} +@implementation WebDataSource (WebInternal) + (NSMutableDictionary *)_repTypesAllowImageTypeOmission:(BOOL)allowImageTypeOmission { @@ -625,7 +374,7 @@ static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class class, if (!repTypes) { repTypes = [[NSMutableDictionary alloc] init]; addTypesFromClass(repTypes, [WebHTMLRepresentation class], [WebHTMLRepresentation supportedNonImageMIMETypes]); - + // Since this is a "secret default" we don't both registering it. BOOL omitPDFSupport = [[NSUserDefaults standardUserDefaults] boolForKey:@"WebKitOmitPDFSupport"]; if (!omitPDFSupport) @@ -640,54 +389,88 @@ static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class class, return repTypes; } -+ (Class)_representationClassForMIMEType:(NSString *)MIMEType +- (void)_decidePolicyForMIMEType:(NSString *)MIMEType decisionListener:(WebPolicyDecisionListener *)listener { - Class repClass; - return [WebView _viewClass:nil andRepresentationClass:&repClass forMIMEType:MIMEType] ? repClass : nil; + WebView *wv = [self _webView]; + [[wv _policyDelegateForwarder] webView:wv decidePolicyForMIMEType:MIMEType + request:[self request] + frame:[self webFrame] + decisionListener:listener]; } -- (WebFrameBridge *)_bridge +- (void)_finishedLoading { - ASSERT(_private->committed); - return [[self webFrame] _bridge]; + _private->gotFirstByte = YES; + [self _commitIfReady]; + + _private->representationFinishedLoading = YES; + [[self representation] finishedLoadingWithDataSource:self]; + [[self _bridge] end]; } -- (void)_commitIfReady +- (void)_setResponse:(NSURLResponse *)response { - if (_private->gotFirstByte && !_private->committed) { - _private->committed = TRUE; - [[self webFrame] _commitProvisionalLoad:nil]; - } + [_private->response release]; + _private->response = [response retain]; } --(void)_makeRepresentation +- (void)_setRequest:(NSURLRequest *)request { - Class repClass = [[self class] _representationClassForMIMEType:[[self response] MIMEType]]; + ASSERT_ARG(request, request != _private->request); - // Check if the data source was already bound? - if (![[self representation] isKindOfClass:repClass]) { - id newRep = repClass != nil ? [[repClass alloc] init] : nil; - [self _setRepresentation:(id )newRep]; - [newRep release]; + // Replacing an unreachable URL with alternate content looks like a server-side + // redirect at this point, but we can replace a committed dataSource. + BOOL handlingUnreachableURL = [request _webDataRequestUnreachableURL] != nil; + if (handlingUnreachableURL) { + _private->committed = NO; } - - [_private->representation setDataSource:self]; -} - -- (void)_commitLoadWithData:(NSData *)data -{ - // Both unloading the old page and parsing the new page may execute JavaScript which destroys the datasource - // by starting a new load, so retain temporarily. - [self retain]; - [self _commitIfReady]; - [[self representation] receivedData:data withDataSource:self]; - [[[[self webFrame] frameView] documentView] dataSourceUpdated:self]; - [self release]; + + // We should never be getting a redirect callback after the data + // source is committed, except in the unreachable URL case. It + // would be a WebFoundation bug if it sent a redirect callback after commit. + ASSERT(!_private->committed); + + NSURLRequest *oldRequest = _private->request; + + _private->request = [request mutableCopy]; + + // Only send webView:didReceiveServerRedirectForProvisionalLoadForFrame: if URL changed. + // Also, don't send it when replacing unreachable URLs with alternate content. + if (!handlingUnreachableURL && ![[oldRequest URL] isEqual: [request URL]]) { + LOG(Redirect, "Server redirect to: %@", [request URL]); + [[[self _webView] _frameLoadDelegateForwarder] webView:[self _webView] + didReceiveServerRedirectForProvisionalLoadForFrame:[self webFrame]]; + } + + [oldRequest release]; } -- (BOOL)_doesProgressiveLoadWithMIMEType:(NSString *)MIMEType +- (void)_setupForReplaceByMIMEType:(NSString *)newMIMEType { - return [[self webFrame] _loadType] != WebFrameLoadTypeReplace || [MIMEType isEqualToString:@"text/html"]; + if (!_private->gotFirstByte) + return; + + WebFrame *frame = [self webFrame]; + NSString *oldMIMEType = [[self response] MIMEType]; + + if (![self _doesProgressiveLoadWithMIMEType:oldMIMEType]) { + [self _revertToProvisionalState]; + [self _commitLoadWithData:[self data]]; + } + + _private->representationFinishedLoading = YES; + [[self representation] finishedLoadingWithDataSource:self]; + [[self _bridge] end]; + + [frame _setLoadType:WebFrameLoadTypeReplace]; + _private->gotFirstByte = NO; + + if ([self _doesProgressiveLoadWithMIMEType:newMIMEType]) + [self _revertToProvisionalState]; + + [[_private->webFrame _frameLoader] stopLoadingSubresources]; + [[_private->webFrame _frameLoader] stopLoadingPlugIns]; + [_private->unarchivingState release]; } -(void)_receivedData:(NSData *)data @@ -698,16 +481,6 @@ static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class class, [self _commitLoadWithData:data]; } -- (void)_finishedLoading -{ - _private->gotFirstByte = YES; - [self _commitIfReady]; - - _private->representationFinishedLoading = YES; - [[self representation] finishedLoadingWithDataSource:self]; - [[self _bridge] end]; -} - - (void)_receivedMainResourceError:(NSError *)error complete:(BOOL)isComplete { // MOVABLE @@ -715,7 +488,7 @@ static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class class, // Retain the bridge because the stop may release the last reference to it. [bridge retain]; - + if (isComplete) { // FIXME: Don't want to do this if an entirely new load is going, so should check // that both data sources on the frame are either self or nil. @@ -725,178 +498,411 @@ static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class class, if ([error code] != NSURLErrorCancelled && [error code] != WebKitErrorPlugInWillHandleLoad) [bridge handleFallbackContent]; } - + [bridge release]; - + [[self webFrame] _receivedMainResourceError:error]; [self _mainReceivedError:error complete:isComplete]; } -- (void)_setIconURL:(NSURL *)URL +- (void)_mainReceivedError:(NSError *)error complete:(BOOL)isComplete { - // Lower priority than typed icon, so ignore this if we already have an iconURL. - if (_private->iconURL == nil) { - [_private->iconURL release]; - _private->iconURL = [URL retain]; + if (![self webFrame]) + return; + + [self _setMainDocumentError:error]; + + if (isComplete) { + [self _setPrimaryLoadComplete:YES]; + [[self webFrame] _checkLoadComplete]; } } -- (void)_setIconURL:(NSURL *)URL withType:(NSString *)iconType +- (BOOL)_defersCallbacks { - // FIXME: Should check to make sure the type is one we know how to handle. - [_private->iconURL release]; - _private->iconURL = [URL retain]; + return _private->defersCallbacks; } -- (void)_defersCallbacksChanged +- (void)_downloadWithLoadingConnection:(NSURLConnection *)connection request:(NSURLRequest *)request response:(NSURLResponse *)r proxy:(WKNSURLConnectionDelegateProxyPtr) proxy { - BOOL defers = [[self _webView] defersCallbacks]; + [WebDownload _downloadWithLoadingConnection:connection + request:request + response:r + delegate:[[self _webView] downloadDelegate] + proxy:proxy]; +} + +- (void)_didFailLoadingWithError:(NSError *)error forResource:(id)identifier +{ + WebView *webView = [self _webView]; - if (defers == _private->defersCallbacks) { - return; - } + [webView _completeProgressForIdentifier:identifier]; + + if (error) + [[webView _resourceLoadDelegateForwarder] webView:webView resource:identifier didFailLoadingWithError:error fromDataSource:self]; +} - _private->defersCallbacks = defers; - [[_private->webFrame _frameLoader] setDefersCallbacks:defers]; +- (void)_didFinishLoadingForResource:(id)identifier +{ + WebView *webView = [self _webView]; + + [webView _completeProgressForIdentifier:identifier]; + + if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidFinishLoadingFromDataSource) + [[webView resourceLoadDelegate] webView:webView resource:identifier didFinishLoadingFromDataSource:self]; + else + [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didFinishLoadingFromDataSource:self]; } -- (BOOL)_defersCallbacks +- (void)_didReceiveData:(NSData *)data contentLength:(int)lengthReceived forResource:(id)identifier { - return _private->defersCallbacks; + WebView *webView = [self _webView]; + + [webView _incrementProgressForIdentifier:identifier data:data]; + + if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidReceiveContentLength) + [[webView resourceLoadDelegate] webView:webView resource:identifier didReceiveContentLength:(WebNSUInteger)lengthReceived fromDataSource:self]; + else + [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didReceiveContentLength:(WebNSUInteger)lengthReceived fromDataSource:self]; } -- (id)_identifierForInitialRequest:(NSURLRequest *)clientRequest +- (void)_didReceiveResponse:(NSURLResponse *)r forResource:(id)identifier { WebView *webView = [self _webView]; + + [self _addResponse:r]; + + [webView _incrementProgressForIdentifier:identifier response:r]; + + if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidReceiveResponse) + [[webView resourceLoadDelegate] webView:webView resource:identifier didReceiveResponse:r fromDataSource:self]; + else + [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didReceiveResponse:r fromDataSource:self]; +} - // The identifier is released after the last callback, rather than in dealloc - // to avoid potential cycles. - if ([webView _resourceLoadDelegateImplementations].delegateImplementsIdentifierForRequest) - return [[[webView resourceLoadDelegate] webView:webView identifierForInitialRequest:clientRequest fromDataSource:self] retain]; +- (void)_didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)currentWebChallenge forResource:(id)identifier +{ + WebView *webView = [self _webView]; + + if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidCancelAuthenticationChallenge) + [[webView resourceLoadDelegate] webView:webView resource:identifier didCancelAuthenticationChallenge:currentWebChallenge fromDataSource:self]; else - return [[[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView identifierForInitialRequest:clientRequest fromDataSource:self] retain]; + [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didCancelAuthenticationChallenge:currentWebChallenge fromDataSource:self]; } -- (NSURLRequest *)_willSendRequest:(NSMutableURLRequest *)clientRequest forResource:(id)identifier redirectResponse:(NSURLResponse *)redirectResponse +- (void)_didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)currentWebChallenge forResource:(id)identifier { WebView *webView = [self _webView]; + + if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidReceiveAuthenticationChallenge) + [[webView resourceLoadDelegate] webView:webView resource:identifier didReceiveAuthenticationChallenge:currentWebChallenge fromDataSource:self]; + else + [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didReceiveAuthenticationChallenge:currentWebChallenge fromDataSource:self]; +} +- (NSURLRequest *)_willSendRequest:(NSMutableURLRequest *)clientRequest forResource:(id)identifier redirectResponse:(NSURLResponse *)redirectResponse +{ + WebView *webView = [self _webView]; + [clientRequest _web_setHTTPUserAgent:[webView userAgentForURL:[clientRequest URL]]]; - + if ([webView _resourceLoadDelegateImplementations].delegateImplementsWillSendRequest) return [[webView resourceLoadDelegate] webView:webView resource:identifier willSendRequest:clientRequest redirectResponse:redirectResponse fromDataSource:self]; else return [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier willSendRequest:clientRequest redirectResponse:redirectResponse fromDataSource:self]; } -- (void)_didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)currentWebChallenge forResource:(id)identifier +- (id)_identifierForInitialRequest:(NSURLRequest *)clientRequest { WebView *webView = [self _webView]; + + // The identifier is released after the last callback, rather than in dealloc + // to avoid potential cycles. + if ([webView _resourceLoadDelegateImplementations].delegateImplementsIdentifierForRequest) + return [[[webView resourceLoadDelegate] webView:webView identifierForInitialRequest:clientRequest fromDataSource:self] retain]; + else + return [[[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView identifierForInitialRequest:clientRequest fromDataSource:self] retain]; +} - if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidReceiveAuthenticationChallenge) - [[webView resourceLoadDelegate] webView:webView resource:identifier didReceiveAuthenticationChallenge:currentWebChallenge fromDataSource:self]; +- (WebResource *)_archivedSubresourceForURL:(NSURL *)URL +{ + return [_private->unarchivingState archivedResourceForURL:URL]; +} + +- (void)_startLoading +{ + [self _prepareForLoadStart]; + + if ([[_private->webFrame _frameLoader] isLoadingMainResource]) + return; + + _private->loadingFromPageCache = NO; + + id identifier; + id resourceLoadDelegate = [[self _webView] resourceLoadDelegate]; + if ([resourceLoadDelegate respondsToSelector:@selector(webView:identifierForInitialRequest:fromDataSource:)]) + identifier = [resourceLoadDelegate webView:[self _webView] identifierForInitialRequest:_private->originalRequest fromDataSource:self]; else - [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didReceiveAuthenticationChallenge:currentWebChallenge fromDataSource:self]; + identifier = [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:[self _webView] identifierForInitialRequest:_private->originalRequest fromDataSource:self]; + + [[_private->webFrame _frameLoader] startLoadingMainResourceWithRequest:_private->request identifier:identifier]; } +- (void)_stopRecordingResponses +{ + _private->stopRecordingResponses = YES; +} -- (void)_didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)currentWebChallenge forResource:(id)identifier +- (double)_loadingStartedTime { - WebView *webView = [self _webView]; + return _private->loadingStartedTime; +} - if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidCancelAuthenticationChallenge) - [[webView resourceLoadDelegate] webView:webView resource:identifier didCancelAuthenticationChallenge:currentWebChallenge fromDataSource:self]; - else - [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didCancelAuthenticationChallenge:currentWebChallenge fromDataSource:self]; +- (void)_replaceSelectionWithArchive:(WebArchive *)archive selectReplacement:(BOOL)selectReplacement +{ + DOMDocumentFragment *fragment = [self _documentFragmentWithArchive:archive]; + if (fragment) + [[self _bridge] replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:NO matchStyle:NO]; } -- (void)_didReceiveResponse:(NSURLResponse *)r forResource:(id)identifier +- (DOMDocumentFragment *)_documentFragmentWithArchive:(WebArchive *)archive { - WebView *webView = [self _webView]; + ASSERT(archive); + WebResource *mainResource = [archive mainResource]; + if (mainResource) { + NSString *MIMEType = [mainResource MIMEType]; + if ([WebView canShowMIMETypeAsHTML:MIMEType]) { + NSString *markupString = [[NSString alloc] initWithData:[mainResource data] encoding:NSUTF8StringEncoding]; + // FIXME: seems poor form to do this as a side effect of getting a document fragment + [self _addToUnarchiveState:archive]; + DOMDocumentFragment *fragment = [[self _bridge] documentFragmentWithMarkupString:markupString baseURLString:[[mainResource URL] _web_originalDataAsString]]; + [markupString release]; + return fragment; + } else if ([[WebFrameBridge supportedImageResourceMIMETypes] containsObject:MIMEType]) { + return [self _documentFragmentWithImageResource:mainResource]; + + } + } + return nil; +} - [self _addResponse:r]; +- (DOMDocumentFragment *)_documentFragmentWithImageResource:(WebResource *)resource +{ + DOMElement *imageElement = [self _imageElementWithImageResource:resource]; + if (!imageElement) + return 0; + DOMDocumentFragment *fragment = [[[self _bridge] DOMDocument] createDocumentFragment]; + [fragment appendChild:imageElement]; + return fragment; +} - [webView _incrementProgressForIdentifier:identifier response:r]; - - if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidReceiveResponse) - [[webView resourceLoadDelegate] webView:webView resource:identifier didReceiveResponse:r fromDataSource:self]; - else - [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didReceiveResponse:r fromDataSource:self]; +- (DOMElement *)_imageElementWithImageResource:(WebResource *)resource +{ + if (!resource) + return 0; + + [self addSubresource:resource]; + + DOMElement *imageElement = [[[self _bridge] DOMDocument] createElement:@"img"]; + + // FIXME: calling _web_originalDataAsString on a file URL returns an absolute path. Workaround this. + NSURL *URL = [resource URL]; + [imageElement setAttribute:@"src" :[URL isFileURL] ? [URL absoluteString] : [URL _web_originalDataAsString]]; + + return imageElement; +} + +- (NSString *)_title +{ + return _private->pageTitle; +} + +- (BOOL)_isStopping +{ + return _private->stopping; +} + +- (void)_setWebFrame:(WebFrame *)frame +{ + [frame retain]; + [_private->webFrame release]; + _private->webFrame = frame; + + [self _defersCallbacksChanged]; + // no need to do _defersCallbacksChanged for subframes since they too + // will be or have been told of their WebFrame +} + +// May return nil if not initialized with a URL. +- (NSURL *)_URL +{ + return [[self request] URL]; +} + +- (void)_loadFromPageCache:(NSDictionary *)pageCache +{ + [self _prepareForLoadStart]; + _private->loadingFromPageCache = YES; + _private->committed = TRUE; + [[self webFrame] _commitProvisionalLoad:pageCache]; +} + +- (WebArchive *)_popSubframeArchiveWithName:(NSString *)frameName +{ + return [_private->unarchivingState popSubframeArchiveWithFrameName:frameName]; +} + +- (void)_setIsClientRedirect:(BOOL)flag +{ + _private->isClientRedirect = flag; +} + +- (void)_setURL:(NSURL *)URL +{ + NSMutableURLRequest *newOriginalRequest = [_private->originalRequestCopy mutableCopy]; + [_private->originalRequestCopy release]; + [newOriginalRequest setURL:URL]; + _private->originalRequestCopy = newOriginalRequest; + + NSMutableURLRequest *newRequest = [_private->request mutableCopy]; + [_private->request release]; + [newRequest setURL:URL]; + _private->request = newRequest; +} + +- (void)_setLastCheckedRequest:(NSURLRequest *)request +{ + NSURLRequest *oldRequest = _private->lastCheckedRequest; + _private->lastCheckedRequest = [request copy]; + [oldRequest release]; +} + +- (void)_defersCallbacksChanged +{ + BOOL defers = [[self _webView] defersCallbacks]; + + if (defers == _private->defersCallbacks) { + return; + } + + _private->defersCallbacks = defers; + [[_private->webFrame _frameLoader] setDefersCallbacks:defers]; +} + +- (NSURLRequest *)_lastCheckedRequest +{ + // It's OK not to make a copy here because we know the caller + // isn't going to modify this request + return [[_private->lastCheckedRequest retain] autorelease]; +} + +// Cancels the data source's pending loads. Conceptually, a data source only loads +// one document at a time, but one document may have many related resources. +// _stopLoading will stop all loads initiated by the data source, +// but not loads initiated by child frames' data sources -- that's the WebFrame's job. +- (void)_stopLoading +{ + // 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->webFrame _frameLoader] stopLoadingIcon]; + + // The same goes for the bridge/part, which may still be parsing. + if (_private->committed) + [[self _bridge] stopLoading]; + + if (![[_private->webFrame _frameLoader] isLoading]) + return; + + [self retain]; + + _private->stopping = YES; + + if ([[_private->webFrame _frameLoader] isLoadingMainResource]) { + // Stop the main resource loader and let it send the cancelled message. + [[_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]]; + } else { + // If there are no resource loaders, we need to manufacture a cancelled message. + // (A back/forward navigation has no resource loaders because its resources are cached.) + [self _mainReceivedError:[self _cancelledError] complete:YES]; + } + + [[_private->webFrame _frameLoader] stopLoadingSubresources]; + [[_private->webFrame _frameLoader] stopLoadingPlugIns]; + + _private->stopping = NO; + + [self release]; } -- (void)_didReceiveData:(NSData *)data contentLength:(int)lengthReceived forResource:(id)identifier +- (WebFrameBridge *)_bridge { - WebView *webView = [self _webView]; - - [webView _incrementProgressForIdentifier:identifier data:data]; - - if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidReceiveContentLength) - [[webView resourceLoadDelegate] webView:webView resource:identifier didReceiveContentLength:(WebNSUInteger)lengthReceived fromDataSource:self]; - else - [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didReceiveContentLength:(WebNSUInteger)lengthReceived fromDataSource:self]; + ASSERT(_private->committed); + return [[self webFrame] _bridge]; } - -- (void)_didFinishLoadingForResource:(id)identifier +- (WebView *)_webView { - WebView *webView = [self _webView]; - - [webView _completeProgressForIdentifier:identifier]; - - if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidFinishLoadingFromDataSource) - [[webView resourceLoadDelegate] webView:webView resource:identifier didFinishLoadingFromDataSource:self]; - else - [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didFinishLoadingFromDataSource:self]; + return [_private->webFrame webView]; } -- (void)_didFailLoadingWithError:(NSError *)error forResource:(id)identifier +- (NSDictionary *)_triggeringAction { - WebView *webView = [self _webView]; - - [webView _completeProgressForIdentifier:identifier]; - - if (error) - [[webView _resourceLoadDelegateForwarder] webView:webView resource:identifier didFailLoadingWithError:error fromDataSource:self]; + return [[_private->triggeringAction retain] autorelease]; } -- (void)_downloadWithLoadingConnection:(NSURLConnection *)connection request:(NSURLRequest *)request response:(NSURLResponse *)r proxy:(WKNSURLConnectionDelegateProxyPtr) proxy +- (void)_setTriggeringAction:(NSDictionary *)action { - [WebDownload _downloadWithLoadingConnection:connection - request:request - response:r - delegate:[[self _webView] downloadDelegate] - proxy:proxy]; + [action retain]; + [_private->triggeringAction release]; + _private->triggeringAction = action; } -- (NSURLRequest *)_originalRequest +- (void)__adoptRequest:(NSMutableURLRequest *)request { - return _private->originalRequestCopy; + if (request != _private->request){ + [_private->request release]; + _private->request = [request retain]; + } } -- (void)_setTriggeringAction:(NSDictionary *)action +- (BOOL)_isDocumentHTML { - [action retain]; - [_private->triggeringAction release]; - _private->triggeringAction = action; + NSString *MIMEType = [[self response] MIMEType]; + return [WebView canShowMIMETypeAsHTML:MIMEType]; } -- (NSDictionary *)_triggeringAction +- (void)_stopLoadingWithError:(NSError *)error { - return [[_private->triggeringAction retain] autorelease]; + [[_private->webFrame _frameLoader] stopLoadingWithError:error]; } -- (NSURLRequest *)_lastCheckedRequest +- (void)_setPrimaryLoadComplete:(BOOL)flag { - // It's OK not to make a copy here because we know the caller - // isn't going to modify this request - return [[_private->lastCheckedRequest retain] autorelease]; + _private->primaryLoadComplete = flag; + + if (flag) { + // FIXME: We could actually load it as soon as we've parsed + // the HEAD section, or determined there isn't one - but + // there's no callback for that. + [self _loadIcon]; + + if ([[_private->webFrame _frameLoader] isLoadingMainResource]) { + [self _setData:[[_private->webFrame _frameLoader] mainResourceData]]; + [[_private->webFrame _frameLoader] releaseMainResourceLoader]; + } + + if ([WebScriptDebugServer listenerCount]) + [[WebScriptDebugServer sharedScriptDebugServer] webView:[[self webFrame] webView] didLoadMainResourceForDataSource:self]; + } } -- (void)_setLastCheckedRequest:(NSURLRequest *)request +- (NSArray *)_responses { - NSURLRequest *oldRequest = _private->lastCheckedRequest; - _private->lastCheckedRequest = [request copy]; - [oldRequest release]; + return _private->responses; } - (BOOL)_loadingFromPageCache @@ -904,96 +910,122 @@ static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class class, return _private->loadingFromPageCache; } -- (void)_addResponse:(NSURLResponse *)r +-(void)_makeRepresentation { - if (!_private->stopRecordingResponses) { - if (!_private->responses) - _private->responses = [[NSMutableArray alloc] init]; - [_private->responses addObject: r]; + Class repClass = [[self class] _representationClassForMIMEType:[[self response] MIMEType]]; + + // Check if the data source was already bound? + if (![[self representation] isKindOfClass:repClass]) { + id newRep = repClass != nil ? [[repClass alloc] init] : nil; + [self _setRepresentation:(id )newRep]; + [newRep release]; } + + [_private->representation setDataSource:self]; } -- (void)_stopRecordingResponses +- (BOOL)_isClientRedirect { - _private->stopRecordingResponses = YES; + return _private->isClientRedirect; } -- (NSArray *)_responses + +- (NSURLRequest *)_originalRequest { - return _private->responses; + return _private->originalRequestCopy; } -- (void)_stopLoadingWithError:(NSError *)error +- (NSURL *)_URLForHistory { - [[_private->webFrame _frameLoader] stopLoadingWithError:error]; + // Return the URL to be used for history and B/F list. + // Returns nil for WebDataProtocol URLs that aren't alternates + // for unreachable URLs, because these can't be stored in history. + NSURL *URL = [_private->originalRequestCopy URL]; + if ([WebDataProtocol _webIsDataProtocolURL:URL]) { + URL = [_private->originalRequestCopy _webDataRequestUnreachableURL]; + } + + return [URL _webkit_canonicalize]; } -- (void)_setWebFrame:(WebFrame *)frame +- (void)_addToUnarchiveState:(WebArchive *)archive { - [frame retain]; - [_private->webFrame release]; - _private->webFrame = frame; - - [self _defersCallbacksChanged]; - // no need to do _defersCallbacksChanged for subframes since they too - // will be or have been told of their WebFrame + if (!_private->unarchivingState) + _private->unarchivingState = [[WebUnarchivingState alloc] init]; + [_private->unarchivingState addArchive:archive]; } -// May return nil if not initialized with a URL. -- (NSURL *)_URL +- (void)_setOverrideEncoding:(NSString *)overrideEncoding { - return [[self request] URL]; + NSString *copy = [overrideEncoding copy]; + [_private->overrideEncoding release]; + _private->overrideEncoding = copy; } -- (NSError *)_mainDocumentError +- (void)_setIconURL:(NSURL *)URL { - return _private->mainDocumentError; + // Lower priority than typed icon, so ignore this if we already have an iconURL. + if (_private->iconURL == nil) { + [_private->iconURL release]; + _private->iconURL = [URL retain]; + } } -- (BOOL)_isDocumentHTML +- (void)_setIconURL:(NSURL *)URL withType:(NSString *)iconType { - NSString *MIMEType = [[self response] MIMEType]; - return [WebView canShowMIMETypeAsHTML:MIMEType]; + // FIXME: Should check to make sure the type is one we know how to handle. + [_private->iconURL release]; + _private->iconURL = [URL retain]; } -- (void)_revertToProvisionalState +- (NSString *)_overrideEncoding { - [self _setRepresentation:nil]; - [[_private->webFrame _frameLoader] setupForReplace]; - _private->committed = NO; + return [[_private->overrideEncoding copy] autorelease]; } -- (void)_setupForReplaceByMIMEType:(NSString *)newMIMEType +- (void)_setTitle:(NSString *)title { - if (!_private->gotFirstByte) + NSString *trimmed; + if (title == nil) { + trimmed = nil; + } else { + trimmed = [title _webkit_stringByTrimmingWhitespace]; + if ([trimmed length] == 0) + trimmed = nil; + } + if (trimmed == nil) { + if (_private->pageTitle == nil) + return; + } else { + if ([_private->pageTitle isEqualToString:trimmed]) + return; + } + + if (!trimmed || [trimmed length] == 0) return; - WebFrame *frame = [self webFrame]; - NSString *oldMIMEType = [[self response] MIMEType]; + [[self _webView] _willChangeValueForKey:_WebMainFrameTitleKey]; + [_private->pageTitle release]; + _private->pageTitle = [trimmed copy]; + [[self _webView] _didChangeValueForKey:_WebMainFrameTitleKey]; - if (![self _doesProgressiveLoadWithMIMEType:oldMIMEType]) { - [self _revertToProvisionalState]; - [self _commitLoadWithData:[self data]]; + // The title doesn't get communicated to the WebView until we are committed. + if (_private->committed) { + NSURL *URLForHistory = [self _URLForHistory]; + if (URLForHistory != nil) { + WebHistoryItem *entry = [[WebHistory optionalSharedHistory] itemForURL:URLForHistory]; + [entry setTitle: _private->pageTitle]; + + // Must update the entries in the back-forward list too. This must go through the WebFrame because + // it has the right notion of the current b/f item. + [[self webFrame] _setTitle:_private->pageTitle]; + + [[self _webView] setMainFrameDocumentReady:YES]; // update observers with new DOMDocument + [[[self _webView] _frameLoadDelegateForwarder] webView:[self _webView] + didReceiveTitle:_private->pageTitle + forFrame:[self webFrame]]; + } } - - _private->representationFinishedLoading = YES; - [[self representation] finishedLoadingWithDataSource:self]; - [[self _bridge] end]; - - [frame _setLoadType:WebFrameLoadTypeReplace]; - _private->gotFirstByte = NO; - - if ([self _doesProgressiveLoadWithMIMEType:newMIMEType]) - [self _revertToProvisionalState]; - - [[_private->webFrame _frameLoader] stopLoadingSubresources]; - [[_private->webFrame _frameLoader] stopLoadingPlugIns]; - [_private->unarchivingState release]; -} - -- (WebResource *)_archivedSubresourceForURL:(NSURL *)URL -{ - return [_private->unarchivingState archivedResourceForURL:URL]; } @end @@ -1164,26 +1196,4 @@ static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class class, } } -- (void)_mainReceivedError:(NSError *)error complete:(BOOL)isComplete -{ - if (![self webFrame]) - return; - - [self _setMainDocumentError:error]; - - if (isComplete) { - [self _setPrimaryLoadComplete:YES]; - [[self webFrame] _checkLoadComplete]; - } -} - -- (void)_decidePolicyForMIMEType:(NSString *)MIMEType decisionListener:(WebPolicyDecisionListener *)listener -{ - WebView *wv = [self _webView]; - [[wv _policyDelegateForwarder] webView:wv decidePolicyForMIMEType:MIMEType - request:[self request] - frame:[self webFrame] - decisionListener:listener]; -} - @end diff --git a/WebKit/WebView/WebDataSourceInternal.h b/WebKit/WebView/WebDataSourceInternal.h index 3dce6e117b0d..091194f6990f 100644 --- a/WebKit/WebView/WebDataSourceInternal.h +++ b/WebKit/WebView/WebDataSourceInternal.h @@ -49,60 +49,52 @@ @protocol WebDocumentRepresentation; @interface WebDataSource (WebInternal) -- (void)_stopLoadingWithError:(NSError *)error; -- (void)_setTitle:(NSString *)title; -- (NSString *)_overrideEncoding; -- (void)_setIconURL:(NSURL *)URL; - (void)_setTitle:(NSString *)title; - (NSString *)_overrideEncoding; - (void)_setIconURL:(NSURL *)URL; - (void)_setIconURL:(NSURL *)URL withType:(NSString *)iconType; -- (NSURLRequest *)_originalRequest; -- (WebView *)_webView; -- (WebResource *)_archivedSubresourceForURL:(NSURL *)URL; -- (void)_addResponse:(NSURLResponse *)r; -- (WebFrameBridge *)_bridge; - (void)_setOverrideEncoding:(NSString *)overrideEncoding; -- (void)_replaceSelectionWithArchive:(WebArchive *)archive selectReplacement:(BOOL)selectReplacement; -- (NSURL *)_URL; -+ (NSMutableDictionary *)_repTypesAllowImageTypeOmission:(BOOL)allowImageTypeOmission; -- (void)_setPrimaryLoadComplete:(BOOL)flag; -- (void)_setMainDocumentError:(NSError *)error; - (void)_addToUnarchiveState:(WebArchive *)archive; - (NSURL *)_URLForHistory; -- (void)_setWebFrame:(WebFrame *)frame; +- (NSURLRequest *)_originalRequest; - (BOOL)_isClientRedirect; - (void)_makeRepresentation; -- (double)_loadingStartedTime; -- (BOOL)_isStopping; -- (void)_finishedLoading; -- (void)_setResponse:(NSURLResponse *)response; -- (void)_setupForReplaceByMIMEType:(NSString *)mimeType; -- (void)_setRequest:(NSURLRequest *)request; -- (void)_receivedData:(NSData *)data; -- (void)_receivedMainResourceError:(NSError *)error complete:(BOOL)isComplete; -- (BOOL)_isDocumentHTML; -- (DOMDocumentFragment *)_documentFragmentWithImageResource:(WebResource *)resource; -- (DOMDocumentFragment *)_documentFragmentWithArchive:(WebArchive *)archive; -- (NSString *)_title; -- (void)_stopRecordingResponses; - (BOOL)_loadingFromPageCache; - (NSArray *)_responses; +- (void)_setPrimaryLoadComplete:(BOOL)flag; - (void)_stopLoading; +- (BOOL)_isDocumentHTML; - (void)__adoptRequest:(NSMutableURLRequest *)request; - (void)_setTriggeringAction:(NSDictionary *)action; - (NSDictionary *)_triggeringAction; +- (WebView *)_webView; +- (WebFrameBridge *)_bridge; +- (void)_stopLoadingWithError:(NSError *)error; - (NSURLRequest *)_lastCheckedRequest; +- (void)_defersCallbacksChanged; - (void)_setLastCheckedRequest:(NSURLRequest *)request; - (void)_setURL:(NSURL *)URL; - (void)_setIsClientRedirect:(BOOL)flag; - (WebArchive *)_popSubframeArchiveWithName:(NSString *)frameName; -- (void)_defersCallbacksChanged; -- (void)_startLoading; - (void)_loadFromPageCache:(NSDictionary *)pageCache; +- (NSURL *)_URL; +- (void)_setWebFrame:(WebFrame *)frame; +- (BOOL)_isStopping; +- (NSString *)_title; - (DOMElement *)_imageElementWithImageResource:(WebResource *)resource; -- (void)_mainReceivedError:(NSError *)error complete:(BOOL)isComplete; -- (BOOL)_defersCallbacks; +- (DOMDocumentFragment *)_documentFragmentWithImageResource:(WebResource *)resource; +- (DOMDocumentFragment *)_documentFragmentWithArchive:(WebArchive *)archive; ++ (NSMutableDictionary *)_repTypesAllowImageTypeOmission:(BOOL)allowImageTypeOmission; +- (void)_replaceSelectionWithArchive:(WebArchive *)archive selectReplacement:(BOOL)selectReplacement; +- (double)_loadingStartedTime; +- (void)_stopRecordingResponses; +- (void)_startLoading; +- (WebResource *)_archivedSubresourceForURL:(NSURL *)URL; +- (double)_loadingStartedTime; +- (void)_stopRecordingResponses; +- (void)_startLoading; +- (WebResource *)_archivedSubresourceForURL:(NSURL *)URL; +- (void)_defersCallbacksChanged; - (id)_identifierForInitialRequest:(NSURLRequest *)clientRequest; - (NSURLRequest *)_willSendRequest:(NSMutableURLRequest *)clientRequest forResource:(id)identifier redirectResponse:(NSURLResponse *)redirectResponse; - (void)_didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)currentWebChallenge forResource:(id)identifier; @@ -112,6 +104,16 @@ - (void)_didFinishLoadingForResource:(id)identifier; - (void)_didFailLoadingWithError:(NSError *)error forResource:(id)identifier; - (void)_downloadWithLoadingConnection:(NSURLConnection *)connection request:(NSURLRequest *)request response:(NSURLResponse *)r proxy:(WKNSURLConnectionDelegateProxyPtr) proxy; -- (BOOL)_privateBrowsingEnabled; +- (BOOL)_defersCallbacks; +- (void)_receivedMainResourceError:(NSError *)error complete:(BOOL)isComplete; +- (void)_receivedData:(NSData *)data; +- (void)_setRequest:(NSURLRequest *)request; +- (void)_setResponse:(NSURLResponse *)response; +- (void)_finishedLoading; +- (void)_setupForReplaceByMIMEType:(NSString *)mimeType; +- (void)_mainReceivedError:(NSError *)error complete:(BOOL)isComplete; - (void)_decidePolicyForMIMEType:(NSString *)MIMEType decisionListener:(WebPolicyDecisionListener *)listener; + + + @end -- 2.36.0