2 * Copyright (C) 2005 Apple Computer, Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #import <WebKit/WebDataSourcePrivate.h>
31 #import <WebKit/DOMHTML.h>
32 #import <WebKit/WebAssertions.h>
33 #import <WebKit/WebArchive.h>
34 #import <WebKit/WebBridge.h>
35 #import <WebKit/WebDataProtocol.h>
36 #import <WebKit/WebDefaultResourceLoadDelegate.h>
37 #import <WebKit/WebDocument.h>
38 #import <WebKit/WebDOMOperationsPrivate.h>
39 #import <WebKit/WebFrameLoadDelegate.h>
40 #import <WebKit/WebFramePrivate.h>
41 #import <WebKit/WebFrameView.h>
42 #import <WebKit/WebHistory.h>
43 #import <WebKit/WebHistoryItemPrivate.h>
44 #import <WebKit/WebHTMLRepresentation.h>
45 #import <WebKit/WebHTMLViewPrivate.h>
46 #import <WebKit/WebIconDatabasePrivate.h>
47 #import <WebKit/WebIconLoader.h>
48 #import <WebKit/WebImageRendererFactory.h>
49 #import <WebKit/WebImageRepresentation.h>
50 #import <WebKit/WebImageView.h>
51 #import <WebKit/WebKitErrorsPrivate.h>
52 #import <WebKit/WebKitLogging.h>
53 #import <WebKit/WebKitNSStringExtras.h>
54 #import <WebKit/WebKitStatisticsPrivate.h>
55 #import <WebKit/WebMainResourceClient.h>
56 #import <WebKit/WebNSObjectExtras.h>
57 #import <WebKit/WebNSURLExtras.h>
58 #ifndef OMIT_TIGER_FEATURES
59 #import <WebKit/WebPDFRepresentation.h>
61 #import <WebKit/WebResourceLoadDelegate.h>
62 #import <WebKit/WebResourcePrivate.h>
63 #import <WebKit/WebTextRepresentation.h>
64 #import <WebKit/WebViewPrivate.h>
66 #import <Foundation/NSURLConnection.h>
67 #import <Foundation/NSURLRequest.h>
68 #import <Foundation/NSURLResponsePrivate.h>
70 @implementation WebDataSourcePrivate
74 // The WebView is only retained while loading, but this object is also
75 // retained while loading, so no need to release here
78 [resourceData release];
79 [representation release];
81 [originalRequest release];
82 [originalRequestCopy release];
84 [subresourceClients release];
85 [plugInStreamClients release];
88 [mainDocumentError release];
91 [ourBackForwardItems release];
92 [triggeringAction release];
93 [lastCheckedRequest release];
96 [subresources release];
97 [pendingSubframeArchives release];
104 @implementation WebDataSource (WebPrivate)
106 - (void)_addSubresources:(NSArray *)subresources
108 NSEnumerator *enumerator = [subresources objectEnumerator];
109 WebResource *subresource;
110 while ((subresource = [enumerator nextObject]) != nil) {
111 [self addSubresource:subresource];
115 - (NSFileWrapper *)_fileWrapperForURL:(NSURL *)URL
117 if ([URL isFileURL]) {
118 NSString *path = [[URL path] stringByResolvingSymlinksInPath];
119 return [[[NSFileWrapper alloc] initWithPath:path] autorelease];
122 WebResource *resource = [self subresourceForURL:URL];
124 return [resource _fileWrapperRepresentation];
127 NSCachedURLResponse *cachedResponse = [_private->webView _cachedResponseForURL:URL];
128 if (cachedResponse) {
129 NSFileWrapper *wrapper = [[[NSFileWrapper alloc] initRegularFileWithContents:[cachedResponse data]] autorelease];
130 [wrapper setPreferredFilename:[[cachedResponse response] suggestedFilename]];
137 - (WebArchive *)_archiveWithMarkupString:(NSString *)markupString nodes:(NSArray *)nodes
139 WebFrame *frame = [self webFrame];
140 NSURLResponse *response = [self response];
141 WebResource *mainResource = [[WebResource alloc] initWithData:[markupString dataUsingEncoding:NSUTF8StringEncoding]
143 MIMEType:[response MIMEType]
144 textEncodingName:@"UTF-8"
145 frameName:[frame name]];
147 NSMutableArray *subframeArchives = [[NSMutableArray alloc] init];
148 NSMutableArray *subresources = [[NSMutableArray alloc] init];
149 NSEnumerator *enumerator = [nodes objectEnumerator];
151 while ((node = [enumerator nextObject]) != nil) {
152 WebFrame *childFrame;
153 if (([node isKindOfClass:[DOMHTMLFrameElement class]] ||
154 [node isKindOfClass:[DOMHTMLIFrameElement class]] ||
155 [node isKindOfClass:[DOMHTMLObjectElement class]]) &&
156 ((childFrame = [(DOMHTMLFrameElement *)node contentFrame]) != nil)) {
157 [subframeArchives addObject:[[childFrame dataSource] _archiveWithCurrentState:YES]];
159 NSEnumerator *enumerator = [[node _subresourceURLs] objectEnumerator];
161 while ((URL = [enumerator nextObject]) != nil) {
162 WebResource *subresource = [self subresourceForURL:URL];
164 [subresources addObject:subresource];
166 ERROR("Failed to archive subresource for %@", URL);
172 WebArchive *archive = [[[WebArchive alloc] initWithMainResource:mainResource subresources:subresources subframeArchives:subframeArchives] autorelease];
173 [mainResource release];
174 [subresources release];
175 [subframeArchives release];
180 - (WebArchive *)_archiveWithCurrentState:(BOOL)currentState
182 if (currentState && [[self representation] conformsToProtocol:@protocol(WebDocumentDOM)]) {
183 return [[(id <WebDocumentDOM>)[self representation] DOMDocument] webArchive];
185 NSEnumerator *enumerator = [[[self webFrame] childFrames] objectEnumerator];
186 NSMutableArray *subframeArchives = [[NSMutableArray alloc] init];
187 WebFrame *childFrame;
188 while ((childFrame = [enumerator nextObject]) != nil) {
189 [subframeArchives addObject:[[childFrame dataSource] _archiveWithCurrentState:currentState]];
191 WebArchive *archive = [[[WebArchive alloc] initWithMainResource:[self mainResource]
192 subresources:[_private->subresources allValues]
193 subframeArchives:subframeArchives] autorelease];
194 [subframeArchives release];
199 - (void)_addSubframeArchives:(NSArray *)subframeArchives
201 if (_private->pendingSubframeArchives == nil) {
202 _private->pendingSubframeArchives = [[NSMutableDictionary alloc] init];
205 NSEnumerator *enumerator = [subframeArchives objectEnumerator];
207 while ((archive = [enumerator nextObject]) != nil) {
208 NSString *frameName = [[archive mainResource] frameName];
210 [_private->pendingSubframeArchives setObject:archive forKey:frameName];
215 - (WebArchive *)_popSubframeArchiveWithName:(NSString *)frameName
217 ASSERT(frameName != nil);
219 WebArchive *archive = [[[_private->pendingSubframeArchives objectForKey:frameName] retain] autorelease];
220 if (archive != nil) {
221 [_private->pendingSubframeArchives removeObjectForKey:frameName];
226 - (DOMElement *)_imageElementWithImageResource:(WebResource *)resource
229 [self addSubresource:resource];
231 DOMElement *imageElement = [[[self _bridge] DOMDocument] createElement:@"img"];
233 // FIXME: calling _web_originalDataAsString on a file URL returns an absolute path. Workaround this.
234 NSURL *URL = [resource URL];
235 [imageElement setAttribute:@"src" :[URL isFileURL] ? [URL absoluteString] : [URL _web_originalDataAsString]];
240 - (DOMDocumentFragment *)_documentFragmentWithImageResource:(WebResource *)resource
242 DOMDocumentFragment *fragment = [[[self _bridge] DOMDocument] createDocumentFragment];
243 [fragment appendChild:[self _imageElementWithImageResource:resource]];
247 - (DOMDocumentFragment *)_documentFragmentWithArchive:(WebArchive *)archive
250 WebResource *mainResource = [archive mainResource];
252 NSString *MIMEType = [mainResource MIMEType];
253 if ([WebView canShowMIMETypeAsHTML:MIMEType]) {
254 NSString *markupString = [[NSString alloc] initWithData:[mainResource data] encoding:NSUTF8StringEncoding];
255 [self _addSubresources:[archive subresources]];
256 [self _addSubframeArchives:[archive subframeArchives]];
257 DOMDocumentFragment *fragment = [[self _bridge] documentFragmentWithMarkupString:markupString baseURLString:[[mainResource URL] _web_originalDataAsString]];
258 [markupString release];
260 } else if ([[[WebImageRendererFactory sharedFactory] supportedMIMETypes] containsObject:MIMEType]) {
261 return [self _documentFragmentWithImageResource:mainResource];
268 - (void)_replaceSelectionWithArchive:(WebArchive *)archive selectReplacement:(BOOL)selectReplacement
270 DOMDocumentFragment *fragment = [self _documentFragmentWithArchive:archive];
272 [[self _bridge] replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:NO matchStyle:NO];
276 - (WebView *)_webView
278 return _private->webView;
281 - (void)_setRepresentation: (id<WebDocumentRepresentation>)representation
283 [_private->representation release];
284 _private->representation = [representation retain];
287 - (void)_setLoading:(BOOL)loading
289 ASSERT_ARG(loading, loading == NO || loading == YES);
291 if (_private->loading == loading) {
295 _private->loading = loading;
299 [_private->webView retain];
301 [_private->webView release];
302 // FIXME: It would be cleanest to set webView to nil here. Keeping a non-retained reference
303 // to the WebView is dangerous. But WebSubresourceClient actually depends on this non-retained
304 // reference when starting loads after the data source has stoppped loading.
309 - (void)_updateLoading
311 [self _setLoading:_private->mainClient || [_private->subresourceClients count]];
314 - (void)_setWebView: (WebView *)webView
316 if (_private->loading) {
318 [_private->webView release];
320 _private->webView = webView;
322 [self _defersCallbacksChanged];
325 - (void)_setData:(NSData *)data
328 [_private->resourceData release];
329 _private->resourceData = data;
332 - (void)_setPrimaryLoadComplete: (BOOL)flag
334 _private->primaryLoadComplete = flag;
337 // FIXME: We could actually load it as soon as we've parsed
338 // the HEAD section, or determined there isn't one - but
339 // there's no callback for that.
342 if (_private->mainClient != nil) {
343 [self _setData:[_private->mainClient resourceData]];
344 [_private->mainClient release];
345 _private->mainClient = nil;
348 [self _updateLoading];
352 - (void)_startLoading
354 [self _startLoading: nil];
358 // Cancels any pending loads. A data source is conceptually only ever loading
359 // one document at a time, although one document may have many related
360 // resources. stopLoading will stop all loads related to the data source. This
361 // method will also stop loads that may be loading in child frames.
364 [self _recursiveStopLoading];
368 - (void)_startLoading: (NSDictionary *)pageCache
370 ASSERT([self _isStopping] == NO);
372 [self _setPrimaryLoadComplete: NO];
374 ASSERT([self webFrame] != nil);
378 // Mark the start loading time.
379 _private->loadingStartedTime = CFAbsoluteTimeGetCurrent();
381 [self _setLoading:YES];
383 [_private->webView _progressStarted:[self webFrame]];
385 [_private->webView _didStartProvisionalLoadForFrame:[self webFrame]];
386 [[_private->webView _frameLoadDelegateForwarder] webView:_private->webView
387 didStartProvisionalLoadForFrame:[self webFrame]];
390 _private->loadingFromPageCache = YES;
391 [self _commitIfReady: pageCache];
392 } else if (!_private->mainClient) {
393 _private->loadingFromPageCache = NO;
396 id resourceLoadDelegate = [_private->webView resourceLoadDelegate];
397 if ([resourceLoadDelegate respondsToSelector:@selector(webView:identifierForInitialRequest:fromDataSource:)])
398 identifier = [resourceLoadDelegate webView:_private->webView identifierForInitialRequest:_private->originalRequest fromDataSource:self];
400 identifier = [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:_private->webView identifierForInitialRequest:_private->originalRequest fromDataSource:self];
402 _private->mainClient = [[WebMainResourceClient alloc] initWithDataSource:self];
403 [_private->mainClient setIdentifier: identifier];
404 [[self webFrame] _addExtraFieldsToRequest:_private->request alwaysFromRequest: NO];
405 if (![_private->mainClient loadWithRequest:_private->request]) {
406 ERROR("could not create WebResourceHandle for URL %@ -- should be caught by policy handler level",
407 [_private->request URL]);
408 [_private->mainClient release];
409 _private->mainClient = nil;
410 [self _updateLoading];
415 - (void)_addSubresourceClient:(WebBaseResourceHandleDelegate *)client
417 if (_private->subresourceClients == nil) {
418 _private->subresourceClients = [[NSMutableArray alloc] init];
420 [_private->subresourceClients addObject:client];
421 [self _setLoading:YES];
424 - (void)_removeSubresourceClient:(WebBaseResourceHandleDelegate *)client
426 [_private->subresourceClients removeObject:client];
427 [self _updateLoading];
430 - (void)_addPlugInStreamClient:(WebBaseResourceHandleDelegate *)client
432 if (_private->plugInStreamClients == nil) {
433 _private->plugInStreamClients = [[NSMutableArray alloc] init];
435 [_private->plugInStreamClients addObject:client];
436 [self _setLoading:YES];
439 - (void)_removePlugInStreamClient:(WebBaseResourceHandleDelegate *)client
441 [_private->plugInStreamClients removeObject:client];
442 [self _updateLoading];
447 return _private->stopping;
450 - (void)_stopLoadingInternal
452 // Always attempt to stop the icon loader because it may still be loading after the data source
453 // is done loading and not stopping it can cause a world leak.
454 [_private->iconLoader stopLoading];
456 if (!_private->loading) {
460 _private->stopping = YES;
462 if(_private->mainClient){
463 // Stop the main handle and let it set the cancelled error.
464 [_private->mainClient cancel];
466 // Main handle is already done. Set the cancelled error.
467 NSError *cancelledError = [NSError _webKitErrorWithDomain:NSURLErrorDomain
468 code:NSURLErrorCancelled
470 [self _setMainDocumentError:cancelledError];
473 NSArray *clients = [_private->subresourceClients copy];
474 [clients makeObjectsPerformSelector:@selector(cancel)];
477 if (_private->committed) {
478 [[self _bridge] closeURL];
482 - (void)_recursiveStopLoading
486 // We depend on the WebView in the webFrame method and we release it in _stopLoading,
487 // so call webFrame first so we don't send a message the released WebView (3129503).
488 [[[self webFrame] childFrames] makeObjectsPerformSelector:@selector(stopLoading)];
489 [self _stopLoadingInternal];
494 - (double)_loadingStartedTime
496 return _private->loadingStartedTime;
499 - (NSURL *)_URLForHistory
501 // Return the URL to be used for history and B/F list.
502 // Returns nil for WebDataProtocol URLs that aren't alternates
503 // for unreachable URLs, because these can't be stored in history.
504 NSURL *URL = [_private->originalRequestCopy URL];
505 if ([WebDataProtocol _webIsDataProtocolURL:URL]) {
506 URL = [_private->originalRequestCopy _webDataRequestUnreachableURL];
509 return [URL _webkit_canonicalize];
512 - (void)_setTitle:(NSString *)title
518 trimmed = [title _webkit_stringByTrimmingWhitespace];
519 if ([trimmed length] == 0)
522 if (trimmed == nil) {
523 if (_private->pageTitle == nil)
526 if ([_private->pageTitle isEqualToString:trimmed])
530 if (!trimmed || [trimmed length] == 0)
533 [_private->webView _willChangeValueForKey: _WebMainFrameTitleKey];
534 [_private->pageTitle release];
535 _private->pageTitle = [trimmed copy];
536 [_private->webView _didChangeValueForKey: _WebMainFrameTitleKey];
538 // The title doesn't get communicated to the WebView until we are committed.
539 if (_private->committed) {
540 NSURL *URLForHistory = [self _URLForHistory];
541 if (URLForHistory != nil) {
542 WebHistoryItem *entry = [[WebHistory optionalSharedHistory] itemForURL:URLForHistory];
543 [entry setTitle: _private->pageTitle];
545 // Must update the entries in the back-forward list too.
546 [_private->ourBackForwardItems makeObjectsPerformSelector:@selector(setTitle:) withObject:_private->pageTitle];
548 [[_private->webView _frameLoadDelegateForwarder] webView:_private->webView
549 didReceiveTitle:_private->pageTitle
550 forFrame:[self webFrame]];
557 return _private->pageTitle;
560 - (void)_setURL:(NSURL *)URL
562 NSMutableURLRequest *newOriginalRequest = [_private->originalRequestCopy mutableCopy];
563 [_private->originalRequestCopy release];
564 [newOriginalRequest setURL:URL];
565 _private->originalRequestCopy = newOriginalRequest;
567 NSMutableURLRequest *newRequest = [_private->request mutableCopy];
568 [_private->request release];
569 [newRequest setURL:URL];
570 _private->request = newRequest;
573 - (void)__adoptRequest:(NSMutableURLRequest *)request
575 if (request != _private->request){
576 [_private->request release];
577 _private->request = [request retain];
581 - (void)_setRequest:(NSURLRequest *)request
583 ASSERT_ARG(request, request != _private->request);
585 // Replacing an unreachable URL with alternate content looks like a server-side
586 // redirect at this point, but we can replace a committed dataSource.
587 BOOL handlingUnreachableURL = [request _webDataRequestUnreachableURL] != nil;
588 if (handlingUnreachableURL) {
589 _private->committed = NO;
592 // We should never be getting a redirect callback after the data
593 // source is committed, except in the unreachable URL case. It
594 // would be a WebFoundation bug if it sent a redirect callback after commit.
595 ASSERT(!_private->committed);
597 NSURLRequest *oldRequest = _private->request;
599 _private->request = [request mutableCopy];
601 // Only send webView:didReceiveServerRedirectForProvisionalLoadForFrame: if URL changed.
602 // Also, don't send it when replacing unreachable URLs with alternate content.
603 if (!handlingUnreachableURL && ![[oldRequest URL] isEqual: [request URL]]) {
604 LOG(Redirect, "Server redirect to: %@", [request URL]);
605 [[_private->webView _frameLoadDelegateForwarder] webView:_private->webView
606 didReceiveServerRedirectForProvisionalLoadForFrame:[self webFrame]];
609 [oldRequest release];
612 - (void)_setResponse:(NSURLResponse *)response
614 [_private->response release];
615 _private->response = [response retain];
618 - (void)_setOverrideEncoding:(NSString *)overrideEncoding
620 NSString *copy = [overrideEncoding copy];
621 [_private->overrideEncoding release];
622 _private->overrideEncoding = copy;
625 - (NSString *)_overrideEncoding
627 return [[_private->overrideEncoding copy] autorelease];
630 - (void)_setIsClientRedirect:(BOOL)flag
632 _private->isClientRedirect = flag;
635 - (BOOL)_isClientRedirect
637 return _private->isClientRedirect;
640 - (void)_addBackForwardItem:(WebHistoryItem *)item
645 if (!_private->ourBackForwardItems) {
646 _private->ourBackForwardItems = [[NSMutableArray alloc] initWithCapacity:1];
648 if ([_private->ourBackForwardItems indexOfObjectIdenticalTo:item] == NSNotFound) {
649 [_private->ourBackForwardItems addObject:item];
653 - (void)_addBackForwardItems:(NSArray *)items
655 if (!items || [items count] == 0) {
658 if (!_private->ourBackForwardItems) {
659 _private->ourBackForwardItems = [items mutableCopy];
661 [_private->ourBackForwardItems addObjectsFromArray:items];
665 - (NSArray *)_backForwardItems
667 return _private->ourBackForwardItems;
670 - (void)_setMainDocumentError: (NSError *)error
673 [_private->mainDocumentError release];
674 _private->mainDocumentError = error;
676 [[self representation] receivedError:error withDataSource:self];
681 [_private->mainDocumentError release];
682 _private->mainDocumentError = nil;
685 + (NSMutableDictionary *)_repTypesAllowImageTypeOmission:(BOOL)allowImageTypeOmission
687 static NSMutableDictionary *repTypes = nil;
688 static BOOL addedImageTypes;
691 repTypes = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
692 [WebHTMLRepresentation class], @"text/html",
693 [WebHTMLRepresentation class], @"text/xml",
694 [WebHTMLRepresentation class], @"text/xsl",
695 [WebHTMLRepresentation class], @"application/xml",
696 [WebHTMLRepresentation class], @"application/xhtml+xml",
697 [WebHTMLRepresentation class], @"application/rss+xml",
698 [WebHTMLRepresentation class], @"application/atom+xml",
699 [WebHTMLRepresentation class], @"application/x-webarchive",
700 [WebTextRepresentation class], @"text/",
701 [WebTextRepresentation class], @"application/x-javascript",
704 #ifndef OMIT_TIGER_FEATURES
705 // Since this is a "secret default" we don't both registering it.
706 BOOL omitPDFSupport = [[NSUserDefaults standardUserDefaults] boolForKey:@"WebKitOmitPDFSupport"];
707 if (!omitPDFSupport) {
708 [repTypes setObject:[WebPDFRepresentation class] forKey:@"text/pdf"];
709 [repTypes setObject:[WebPDFRepresentation class] forKey:@"application/pdf"];
714 if (!addedImageTypes && !allowImageTypeOmission) {
715 NSEnumerator *enumerator = [[WebImageView supportedImageMIMETypes] objectEnumerator];
717 while ((mime = [enumerator nextObject]) != nil) {
718 // Don't clobber previously-registered rep classes.
719 if ([repTypes objectForKey:mime] == nil) {
720 [repTypes setObject:[WebImageRepresentation class] forKey:mime];
723 addedImageTypes = YES;
729 + (Class)_representationClassForMIMEType:(NSString *)MIMEType
732 return [WebView _viewClass:nil andRepresentationClass:&repClass forMIMEType:MIMEType] ? repClass : nil;
735 - (WebBridge *)_bridge
737 ASSERT(_private->committed);
738 return [[self webFrame] _bridge];
743 return _private->committed;
746 - (void)_commitIfReady: (NSDictionary *)pageCache
748 if (_private->loadingFromPageCache || (_private->gotFirstByte && !_private->committed)) {
749 WebFrame *frame = [self webFrame];
750 WebFrameLoadType loadType = [frame _loadType];
751 bool reload = loadType == WebFrameLoadTypeReload
752 || loadType == WebFrameLoadTypeReloadAllowingStaleData;
754 NSDictionary *headers = [_private->response isKindOfClass:[NSHTTPURLResponse class]]
755 ? [(NSHTTPURLResponse *)_private->response allHeaderFields] : nil;
757 [frame _closeOldDataSources];
759 LOG(Loading, "committed resource = %@", [[self request] URL]);
760 _private->committed = TRUE;
762 [self _makeRepresentation];
764 [frame _transitionToCommitted: pageCache];
766 NSURL *baseURL = [[self request] _webDataRequestBaseURL];
772 URL = [_private->response URL];
774 // WebCore will crash if given an empty URL here.
775 // FIXME: could use CFURL, when available, range API to save an allocation here
776 if (!URL || [URL _web_isEmpty])
777 URL = [NSURL URLWithString:@"about:blank"];
779 [[self _bridge] openURL:URL
781 contentType:[_private->response MIMEType]
782 refresh:[headers objectForKey:@"Refresh"]
783 lastModified:(pageCache ? nil : [_private->response _lastModifiedDate])
784 pageCache:pageCache];
790 - (void)_commitIfReady
792 [self _commitIfReady: nil];
795 -(void)_makeRepresentation
797 Class repClass = [[self class] _representationClassForMIMEType:[[self response] MIMEType]];
799 // Check if the data source was already bound?
800 if (![[self representation] isKindOfClass:repClass]) {
801 id newRep = repClass != nil ? [[repClass alloc] init] : nil;
802 [self _setRepresentation:(id <WebDocumentRepresentation>)newRep];
806 [_private->representation setDataSource:self];
809 -(void)_receivedData:(NSData *)data
811 _private->gotFirstByte = YES;
812 [self _commitIfReady];
814 // parsing some of the page can result in running a script which
815 // could possibly destroy the frame and data source. So retain
818 [[self representation] receivedData:data withDataSource:self];
819 [[[[self webFrame] frameView] documentView] dataSourceUpdated:self];
823 - (void)_finishedLoading
825 _private->gotFirstByte = YES;
826 [self _commitIfReady];
828 [[self representation] finishedLoadingWithDataSource:self];
829 // Since we've sent openURL to the bridge, it's important to send end too, so that WebCore
830 // can realize that the load is completed.
831 [[self _bridge] end];
834 - (void)_receivedMainResourceError:(NSError *)error complete:(BOOL)isComplete
837 // Can't call [self _bridge] because we might not have commited yet
838 [[[self webFrame] _bridge] stop];
839 [[[self webFrame] _bridge] mainResourceError];
842 [[self webFrame] _receivedMainResourceError:error];
843 [[self _webView] _mainReceivedError:error
845 complete:isComplete];
848 - (void)_updateIconDatabaseWithURL:(NSURL *)iconURL
850 ASSERT([[WebIconDatabase sharedIconDatabase] _isEnabled]);
852 WebIconDatabase *iconDB = [WebIconDatabase sharedIconDatabase];
854 // Bind the URL of the original request and the final URL to the icon URL.
855 [iconDB _setIconURL:[iconURL _web_originalDataAsString] forURL:[[self _URL] _web_originalDataAsString]];
856 [iconDB _setIconURL:[iconURL _web_originalDataAsString] forURL:[[[self _originalRequest] URL] _web_originalDataAsString]];
859 if ([self webFrame] == [_private->webView mainFrame])
860 [_private->webView _willChangeValueForKey:_WebMainFrameIconKey];
862 NSImage *icon = [iconDB iconForURL:[[self _URL] _web_originalDataAsString] withSize:WebIconSmallSize];
863 [[_private->webView _frameLoadDelegateForwarder] webView:_private->webView
865 forFrame:[self webFrame]];
867 if ([self webFrame] == [_private->webView mainFrame])
868 [_private->webView _didChangeValueForKey:_WebMainFrameIconKey];
871 - (void)_iconLoaderReceivedPageIcon:(WebIconLoader *)iconLoader
873 [self _updateIconDatabaseWithURL:[iconLoader URL]];
878 // 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 save by the DB.
879 if ([self webFrame] != [[self _webView] mainFrame] || _private->mainDocumentError || _private->iconLoader ||
880 ![[WebIconDatabase sharedIconDatabase] _isEnabled]) {
884 if(!_private->iconURL){
885 // No icon URL from the LINK tag so try the server's root.
886 // This is only really a feature of http or https, so don't try this with other protocols.
887 NSString *scheme = [[self _URL] scheme];
888 if([scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"]){
889 _private->iconURL = [[[NSURL _web_URLWithDataAsString:@"/favicon.ico"
890 relativeToURL:[self _URL]] absoluteURL] retain];
894 if(_private->iconURL != nil){
895 if([[WebIconDatabase sharedIconDatabase] _hasIconForIconURL:[_private->iconURL _web_originalDataAsString]]){
896 [self _updateIconDatabaseWithURL:_private->iconURL];
898 ASSERT(!_private->iconLoader);
899 NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:_private->iconURL];
900 [[self webFrame] _addExtraFieldsToRequest:request alwaysFromRequest:NO];
901 _private->iconLoader = [[WebIconLoader alloc] initWithRequest:request];
903 [_private->iconLoader setDelegate:self];
904 [_private->iconLoader setDataSource:self];
905 [_private->iconLoader startLoading];
910 - (void)_setIconURL:(NSURL *)URL
912 // Lower priority than typed icon, so ignore this if we already have an iconURL.
913 if (_private->iconURL == nil) {
914 [_private->iconURL release];
915 _private->iconURL = [URL retain];
919 - (void)_setIconURL:(NSURL *)URL withType:(NSString *)iconType
921 // FIXME: Should check to make sure the type is one we know how to handle.
922 [_private->iconURL release];
923 _private->iconURL = [URL retain];
926 - (void)_defersCallbacksChanged
928 BOOL defers = [_private->webView defersCallbacks];
930 if (defers == _private->defersCallbacks) {
934 _private->defersCallbacks = defers;
935 [_private->mainClient setDefersCallbacks:defers];
937 NSEnumerator *e = [_private->subresourceClients objectEnumerator];
938 WebBaseResourceHandleDelegate *client;
939 while ((client = [e nextObject])) {
940 [client setDefersCallbacks:defers];
942 e = [_private->plugInStreamClients objectEnumerator];
943 while ((client = [e nextObject])) {
944 [client setDefersCallbacks:defers];
947 // It's OK to use the internal version of getting the child
948 // frames, since undeferring callbacks will not do any immediate
949 // work, and so the set of frames can't change out from under us.
950 [[[self webFrame] _internalChildFrames] makeObjectsPerformSelector:@selector(_defersCallbacksChanged)];
953 - (NSURLRequest *)_originalRequest
955 return _private->originalRequestCopy;
958 - (void)_setTriggeringAction:(NSDictionary *)action
961 [_private->triggeringAction release];
962 _private->triggeringAction = action;
965 - (NSDictionary *)_triggeringAction
967 return [[_private->triggeringAction retain] autorelease];
971 - (NSURLRequest *)_lastCheckedRequest
973 // It's OK not to make a copy here because we know the caller
974 // isn't going to modify this request
975 return [[_private->lastCheckedRequest retain] autorelease];
978 - (void)_setLastCheckedRequest:(NSURLRequest *)request
980 NSURLRequest *oldRequest = _private->lastCheckedRequest;
981 _private->lastCheckedRequest = [request copy];
982 [oldRequest release];
985 - (void)_setJustOpenedForTargetedLink:(BOOL)justOpened
987 _private->justOpenedForTargetedLink = justOpened;
990 - (BOOL)_justOpenedForTargetedLink
992 return _private->justOpenedForTargetedLink;
995 - (void)_setStoredInPageCache:(BOOL)f
997 _private->storedInPageCache = f;
1000 - (BOOL)_storedInPageCache
1002 return _private->storedInPageCache;
1005 - (BOOL)_loadingFromPageCache
1007 return _private->loadingFromPageCache;
1010 - (void)_addResponse: (NSURLResponse *)r
1012 if (!_private->stopRecordingResponses) {
1013 if (!_private->responses)
1014 _private->responses = [[NSMutableArray alloc] init];
1015 [_private->responses addObject: r];
1019 - (void)_stopRecordingResponses
1021 _private->stopRecordingResponses = YES;
1024 - (NSArray *)_responses
1026 return _private->responses;
1029 - (void)_stopLoadingWithError:(NSError *)error
1031 [_private->mainClient cancelWithError:error];
1034 - (void)_setWebFrame:(WebFrame *)frame
1037 [_private->webFrame release];
1038 _private->webFrame = frame;
1041 // May return nil if not initialized with a URL.
1044 return [[self request] URL];
1047 - (NSString *)_stringWithData:(NSData *)data
1049 NSString *textEncodingName = [self textEncodingName];
1051 if (textEncodingName) {
1052 return [WebBridge stringWithData:data textEncodingName:textEncodingName];
1054 return [WebBridge stringWithData:data textEncoding:kCFStringEncodingISOLatin1];
1058 - (NSError *)_mainDocumentError
1060 return _private->mainDocumentError;
1063 - (BOOL)_isDocumentHTML
1065 NSString *MIMEType = [[self response] MIMEType];
1066 return [WebView canShowMIMETypeAsHTML:MIMEType];
1071 @implementation WebDataSource
1073 -(id)initWithRequest:(NSURLRequest *)request
1075 self = [super init];
1080 _private = [[WebDataSourcePrivate alloc] init];
1081 _private->originalRequest = [request retain];
1082 _private->originalRequestCopy = [request copy];
1084 _private->subresources = [[NSMutableDictionary alloc] init];
1086 LOG(Loading, "creating datasource for %@", [request URL]);
1087 _private->request = [_private->originalRequest mutableCopy];
1089 ++WebDataSourceCount;
1096 --WebDataSourceCount;
1098 [_private->iconLoader setDelegate:nil];
1106 --WebDataSourceCount;
1108 [_private->iconLoader setDelegate:nil];
1115 return _private->resourceData != nil ? _private->resourceData : [_private->mainClient resourceData];
1118 - (id <WebDocumentRepresentation>) representation
1120 return _private->representation;
1123 - (WebFrame *)webFrame
1125 return _private->webFrame;
1128 -(NSURLRequest *)initialRequest
1130 NSURLRequest *clientRequest = [_private->originalRequest _webDataRequestExternalRequest];
1132 clientRequest = _private->originalRequest;
1133 return clientRequest;
1136 -(NSMutableURLRequest *)request
1138 NSMutableURLRequest *clientRequest = [_private->request _webDataRequestExternalRequest];
1140 clientRequest = _private->request;
1141 return clientRequest;
1144 - (NSURLResponse *)response
1146 return _private->response;
1149 - (NSString *)textEncodingName
1151 NSString *textEncodingName = [self _overrideEncoding];
1153 if (!textEncodingName) {
1154 textEncodingName = [[self response] textEncodingName];
1156 return textEncodingName;
1159 // Returns YES if there are any pending loads.
1162 // Once a frame has loaded, we no longer need to consider subresources,
1163 // but we still need to consider subframes.
1164 if ([[self webFrame] _state] != WebFrameStateComplete) {
1165 if (!_private->primaryLoadComplete && _private->loading) {
1168 if ([_private->subresourceClients count]) {
1171 if (![[[self webFrame] _bridge] doneProcessingData])
1175 // Put in the auto-release pool because it's common to call this from a run loop source,
1176 // and then the entire list of frames lasts until the next autorelease.
1177 NSAutoreleasePool *pool = [NSAutoreleasePool new];
1179 // It's OK to use the internal version of getting the child
1180 // frames, since nothing we do here can possibly change the set of
1182 NSEnumerator *e = [[[self webFrame] _internalChildFrames] objectEnumerator];
1183 WebFrame *childFrame;
1184 while ((childFrame = [e nextObject])) {
1185 if ([[childFrame dataSource] isLoading] || [[childFrame provisionalDataSource] isLoading]) {
1190 #if BUILDING_ON_PANTHER
1196 return childFrame != nil;
1200 // Returns nil or the page title.
1201 - (NSString *)pageTitle
1203 return [[self representation] title];
1206 - (NSURL *)unreachableURL
1208 return [_private->originalRequest _webDataRequestUnreachableURL];
1211 - (WebArchive *)webArchive
1213 return [self _archiveWithCurrentState:NO];
1216 - (WebResource *)mainResource
1218 NSURLResponse *response = [self response];
1219 return [[[WebResource alloc] initWithData:[self data]
1221 MIMEType:[response MIMEType]
1222 textEncodingName:[response textEncodingName]
1223 frameName:[[self webFrame] name]] autorelease];
1226 - (NSArray *)subresources
1228 return [_private->subresources allValues];
1231 - (WebResource *)subresourceForURL:(NSURL *)URL
1233 return [_private->subresources objectForKey:[URL _web_originalDataAsString]];
1236 - (void)addSubresource:(WebResource *)subresource
1239 [_private->subresources setObject:subresource forKey:[[subresource URL] _web_originalDataAsString]];
1241 ASSERT_NOT_REACHED();