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 "WebDataSource.h"
31 #import "WebArchive.h"
32 #import "WebArchiver.h"
33 #import "WebDOMOperationsPrivate.h"
34 #import "WebDataProtocol.h"
35 #import "WebDataSourceInternal.h"
36 #import "WebDefaultResourceLoadDelegate.h"
37 #import "WebDocument.h"
38 #import "WebDownloadInternal.h"
39 #import "WebFrameBridge.h"
40 #import "WebFrameInternal.h"
41 #import "WebFrameLoader.h"
42 #import "WebFrameLoadDelegate.h"
43 #import "WebFrameView.h"
44 #import "WebHTMLRepresentation.h"
45 #import "WebHTMLViewPrivate.h"
46 #import "WebHistory.h"
47 #import "WebHistoryItemPrivate.h"
48 #import "WebIconDatabasePrivate.h"
49 #import "WebKitErrorsPrivate.h"
50 #import "WebKitLogging.h"
51 #import "WebKitNSStringExtras.h"
52 #import "WebKitStatisticsPrivate.h"
53 #import "WebNSObjectExtras.h"
54 #import "WebNSURLExtras.h"
55 #import "WebNSURLRequestExtras.h"
56 #import "WebPDFRepresentation.h"
57 #import "WebPreferences.h"
58 #import "WebResourceLoadDelegate.h"
59 #import "WebResourcePrivate.h"
60 #import "WebScriptDebugServerPrivate.h"
61 #import "WebUnarchivingState.h"
62 #import "WebViewInternal.h"
63 #import <Foundation/NSURLConnection.h>
64 #import <Foundation/NSURLRequest.h>
65 #import <JavaScriptCore/Assertions.h>
66 #import <WebKit/DOMHTML.h>
67 #import <WebKitSystemInterface.h>
68 #import "WebDocumentLoadState.h"
70 @interface WebDataSourcePrivate : NSObject
74 WebDocumentLoadState *loadState;
76 id <WebDocumentRepresentation> representation;
78 // A reference to actual request used to create the data source.
79 // This should only be used by the resourceLoadDelegate's
80 // identifierForInitialRequest:fromDatasource: method. It is
81 // not guaranteed to remain unchanged, as requests are mutable.
82 NSURLRequest *originalRequest;
84 // A copy of the original request used to create the data source.
85 // We have to copy the request because requests are mutable.
86 NSURLRequest *originalRequestCopy;
88 // The 'working' request for this datasource. It may be mutated
89 // several times from the original request to include additional
90 // headers, cookie information, canonicalization and redirects.
91 NSMutableURLRequest *request;
93 NSURLResponse *response;
95 // The time when the data source was told to start loading.
96 double loadingStartedTime;
98 BOOL primaryLoadComplete;
102 BOOL isClientRedirect;
107 NSString *overrideEncoding;
109 // Error associated with main document.
110 NSError *mainDocumentError;
112 BOOL gotFirstByte; // got first byte
113 BOOL committed; // This data source has been committed
114 BOOL representationFinishedLoading;
116 BOOL defersCallbacks;
120 // The action that triggered loading of this data source -
121 // we keep this around for the benefit of the various policy
123 NSDictionary *triggeringAction;
125 // The last request that we checked click policy for - kept around
126 // so we can avoid asking again needlessly.
127 NSURLRequest *lastCheckedRequest;
129 // We retain all the received responses so we can play back the
130 // WebResourceLoadDelegate messages if the item is loaded from the
132 NSMutableArray *responses;
133 BOOL stopRecordingResponses;
135 BOOL loadingFromPageCache;
139 NSMutableDictionary *subresources;
141 WebUnarchivingState *unarchivingState;
143 BOOL supportsMultipartContent;
148 @implementation WebDataSourcePrivate
154 [representation release];
156 [originalRequest release];
157 [originalRequestCopy release];
160 [mainDocumentError release];
162 [triggeringAction release];
163 [lastCheckedRequest release];
166 [unarchivingState release];
173 @interface WebDataSource (WebFileInternal)
176 @implementation WebDataSource (WebFileInternal)
178 - (void)_setRepresentation: (id<WebDocumentRepresentation>)representation
180 [_private->representation release];
181 _private->representation = [representation retain];
182 _private->representationFinishedLoading = NO;
187 // Don't load an icon if 1) this is not the main frame 2) we ended in error
188 // 3) they aren't saved by the DB
189 if ([self webFrame] != [[self _webView] mainFrame] || _private->mainDocumentError || ![[WebIconDatabase sharedIconDatabase] _isEnabled])
192 if (!_private->iconURL) {
193 // No icon URL from the LINK tag so try the server's root.
194 // This is only really a feature of http or https, so don't try this with other protocols.
195 NSString *scheme = [[self _URL] scheme];
196 if([scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"]){
197 _private->iconURL = [[[NSURL _web_URLWithDataAsString:@"/favicon.ico"
198 relativeToURL:[self _URL]] absoluteURL] retain];
202 if (_private->iconURL != nil) {
203 // If we have the icon already, we'll still see if we're manually reloading or if the icon is expired
204 // If so, kick off a reload of the icon
205 // If we don't have the icon already, kick off the initial load
206 if ([[WebIconDatabase sharedIconDatabase] _hasEntryForIconURL:[_private->iconURL _web_originalDataAsString]]) {
207 [[_private->webFrame _frameLoader] _updateIconDatabaseWithURL:_private->iconURL];
208 if ([[self webFrame] _loadType] == WebFrameLoadTypeReload || [[WebIconDatabase sharedIconDatabase] isIconExpiredForIconURL:[_private->iconURL _web_originalDataAsString]])
209 [[WebIconDatabase sharedIconDatabase] loadIconFromURL:[_private->iconURL _web_originalDataAsString]];
211 [[_private->webFrame _frameLoader] _notifyIconChanged:_private->iconURL];
213 NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:_private->iconURL];
214 [[self webFrame] _addExtraFieldsToRequest:request mainResource:YES alwaysFromRequest:NO];
215 [[_private->webFrame _frameLoader] loadIconWithRequest:request];
221 - (NSError *)_cancelledError
223 return [NSError _webKitErrorWithDomain:NSURLErrorDomain
224 code:NSURLErrorCancelled
228 - (void)_setMainDocumentError: (NSError *)error
231 [_private->mainDocumentError release];
232 _private->mainDocumentError = error;
234 if (!_private->representationFinishedLoading) {
235 _private->representationFinishedLoading = YES;
236 [[self representation] receivedError:error withDataSource:self];
242 [_private->mainDocumentError release];
243 _private->mainDocumentError = nil;
246 - (void)_prepareForLoadStart
248 ASSERT(![self _isStopping]);
249 [self _setPrimaryLoadComplete:NO];
250 ASSERT([self webFrame] != nil);
253 // Mark the start loading time.
254 _private->loadingStartedTime = CFAbsoluteTimeGetCurrent();
256 [[self _webView] _progressStarted:[self webFrame]];
257 [[self _webView] _didStartProvisionalLoadForFrame:[self webFrame]];
258 [[[self _webView] _frameLoadDelegateForwarder] webView:[self _webView]
259 didStartProvisionalLoadForFrame:[self webFrame]];
262 static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class class, NSArray *supportTypes)
264 NSEnumerator *enumerator = [supportTypes objectEnumerator];
265 ASSERT(enumerator != nil);
266 NSString *mime = nil;
267 while ((mime = [enumerator nextObject]) != nil) {
268 // Don't clobber previously-registered classes.
269 if ([allTypes objectForKey:mime] == nil)
270 [allTypes setObject:class forKey:mime];
274 + (Class)_representationClassForMIMEType:(NSString *)MIMEType
277 return [WebView _viewClass:nil andRepresentationClass:&repClass forMIMEType:MIMEType] ? repClass : nil;
280 - (void)_commitIfReady
282 if (_private->gotFirstByte && !_private->committed) {
283 _private->committed = TRUE;
284 [[self webFrame] _commitProvisionalLoad:nil];
288 - (void)_commitLoadWithData:(NSData *)data
290 // Both unloading the old page and parsing the new page may execute JavaScript which destroys the datasource
291 // by starting a new load, so retain temporarily.
293 [self _commitIfReady];
294 [[self representation] receivedData:data withDataSource:self];
295 [[[[self webFrame] frameView] documentView] dataSourceUpdated:self];
299 - (BOOL)_doesProgressiveLoadWithMIMEType:(NSString *)MIMEType
301 return [[self webFrame] _loadType] != WebFrameLoadTypeReplace || [MIMEType isEqualToString:@"text/html"];
304 - (void)_addResponse:(NSURLResponse *)r
306 if (!_private->stopRecordingResponses) {
307 if (!_private->responses)
308 _private->responses = [[NSMutableArray alloc] init];
309 [_private->responses addObject: r];
313 - (void)_revertToProvisionalState
315 [self _setRepresentation:nil];
316 [[_private->webFrame _frameLoader] setupForReplace];
317 _private->committed = NO;
322 @implementation WebDataSource (WebPrivate)
324 - (NSError *)_mainDocumentError
326 return _private->mainDocumentError;
329 - (void)_addSubframeArchives:(NSArray *)subframeArchives
331 NSEnumerator *enumerator = [subframeArchives objectEnumerator];
333 while ((archive = [enumerator nextObject]) != nil)
334 [self _addToUnarchiveState:archive];
337 - (NSFileWrapper *)_fileWrapperForURL:(NSURL *)URL
339 if ([URL isFileURL]) {
340 NSString *path = [[URL path] stringByResolvingSymlinksInPath];
341 return [[[NSFileWrapper alloc] initWithPath:path] autorelease];
344 WebResource *resource = [self subresourceForURL:URL];
346 return [resource _fileWrapperRepresentation];
349 NSCachedURLResponse *cachedResponse = [[self _webView] _cachedResponseForURL:URL];
350 if (cachedResponse) {
351 NSFileWrapper *wrapper = [[[NSFileWrapper alloc] initRegularFileWithContents:[cachedResponse data]] autorelease];
352 [wrapper setPreferredFilename:[[cachedResponse response] suggestedFilename]];
361 @implementation WebDataSource (WebInternal)
363 + (NSMutableDictionary *)_repTypesAllowImageTypeOmission:(BOOL)allowImageTypeOmission
365 static NSMutableDictionary *repTypes = nil;
366 static BOOL addedImageTypes = NO;
369 repTypes = [[NSMutableDictionary alloc] init];
370 addTypesFromClass(repTypes, [WebHTMLRepresentation class], [WebHTMLRepresentation supportedNonImageMIMETypes]);
372 // Since this is a "secret default" we don't both registering it.
373 BOOL omitPDFSupport = [[NSUserDefaults standardUserDefaults] boolForKey:@"WebKitOmitPDFSupport"];
375 addTypesFromClass(repTypes, [WebPDFRepresentation class], [WebPDFRepresentation supportedMIMETypes]);
378 if (!addedImageTypes && !allowImageTypeOmission) {
379 addTypesFromClass(repTypes, [WebHTMLRepresentation class], [WebHTMLRepresentation supportedImageMIMETypes]);
380 addedImageTypes = YES;
386 - (void)_decidePolicyForMIMEType:(NSString *)MIMEType decisionListener:(WebPolicyDecisionListener *)listener
388 WebView *wv = [self _webView];
389 [[wv _policyDelegateForwarder] webView:wv decidePolicyForMIMEType:MIMEType
390 request:[self request]
391 frame:[self webFrame]
392 decisionListener:listener];
395 - (void)_finishedLoading
397 _private->gotFirstByte = YES;
398 [self _commitIfReady];
400 _private->representationFinishedLoading = YES;
401 [[self representation] finishedLoadingWithDataSource:self];
402 [[self _bridge] end];
405 - (void)_setResponse:(NSURLResponse *)response
407 [_private->response release];
408 _private->response = [response retain];
411 - (void)_setRequest:(NSURLRequest *)request
413 ASSERT_ARG(request, request != _private->request);
415 // Replacing an unreachable URL with alternate content looks like a server-side
416 // redirect at this point, but we can replace a committed dataSource.
417 BOOL handlingUnreachableURL = [request _webDataRequestUnreachableURL] != nil;
418 if (handlingUnreachableURL) {
419 _private->committed = NO;
422 // We should never be getting a redirect callback after the data
423 // source is committed, except in the unreachable URL case. It
424 // would be a WebFoundation bug if it sent a redirect callback after commit.
425 ASSERT(!_private->committed);
427 NSURLRequest *oldRequest = _private->request;
429 _private->request = [request mutableCopy];
431 // Only send webView:didReceiveServerRedirectForProvisionalLoadForFrame: if URL changed.
432 // Also, don't send it when replacing unreachable URLs with alternate content.
433 if (!handlingUnreachableURL && ![[oldRequest URL] isEqual: [request URL]]) {
434 LOG(Redirect, "Server redirect to: %@", [request URL]);
435 [[[self _webView] _frameLoadDelegateForwarder] webView:[self _webView]
436 didReceiveServerRedirectForProvisionalLoadForFrame:[self webFrame]];
439 [oldRequest release];
442 - (void)_setupForReplaceByMIMEType:(NSString *)newMIMEType
444 if (!_private->gotFirstByte)
447 WebFrame *frame = [self webFrame];
448 NSString *oldMIMEType = [[self response] MIMEType];
450 if (![self _doesProgressiveLoadWithMIMEType:oldMIMEType]) {
451 [self _revertToProvisionalState];
452 [self _commitLoadWithData:[self data]];
455 _private->representationFinishedLoading = YES;
456 [[self representation] finishedLoadingWithDataSource:self];
457 [[self _bridge] end];
459 [frame _setLoadType:WebFrameLoadTypeReplace];
460 _private->gotFirstByte = NO;
462 if ([self _doesProgressiveLoadWithMIMEType:newMIMEType])
463 [self _revertToProvisionalState];
465 [[_private->webFrame _frameLoader] stopLoadingSubresources];
466 [[_private->webFrame _frameLoader] stopLoadingPlugIns];
467 [_private->unarchivingState release];
470 -(void)_receivedData:(NSData *)data
472 _private->gotFirstByte = YES;
474 if ([self _doesProgressiveLoadWithMIMEType:[[self response] MIMEType]])
475 [self _commitLoadWithData:data];
478 - (void)_receivedMainResourceError:(NSError *)error complete:(BOOL)isComplete
481 WebFrameBridge *bridge = [[self webFrame] _bridge];
483 // Retain the bridge because the stop may release the last reference to it.
487 // FIXME: Don't want to do this if an entirely new load is going, so should check
488 // that both data sources on the frame are either self or nil.
489 // Can't call [self _bridge] because we might not have commited yet
491 // FIXME: WebKitErrorPlugInWillHandleLoad is a workaround for the cancel we do to prevent loading plugin content twice. See <rdar://problem/4258008>
492 if ([error code] != NSURLErrorCancelled && [error code] != WebKitErrorPlugInWillHandleLoad)
493 [bridge handleFallbackContent];
498 [[self webFrame] _receivedMainResourceError:error];
499 [self _mainReceivedError:error complete:isComplete];
502 - (void)_mainReceivedError:(NSError *)error complete:(BOOL)isComplete
504 if (![self webFrame])
507 [self _setMainDocumentError:error];
510 [self _setPrimaryLoadComplete:YES];
511 [[self webFrame] _checkLoadComplete];
515 - (BOOL)_defersCallbacks
517 return _private->defersCallbacks;
520 - (void)_downloadWithLoadingConnection:(NSURLConnection *)connection request:(NSURLRequest *)request response:(NSURLResponse *)r proxy:(WKNSURLConnectionDelegateProxyPtr) proxy
522 [WebDownload _downloadWithLoadingConnection:connection
525 delegate:[[self _webView] downloadDelegate]
529 - (void)_didFailLoadingWithError:(NSError *)error forResource:(id)identifier
531 WebView *webView = [self _webView];
533 [webView _completeProgressForIdentifier:identifier];
536 [[webView _resourceLoadDelegateForwarder] webView:webView resource:identifier didFailLoadingWithError:error fromDataSource:self];
539 - (void)_didFinishLoadingForResource:(id)identifier
541 WebView *webView = [self _webView];
543 [webView _completeProgressForIdentifier:identifier];
545 if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidFinishLoadingFromDataSource)
546 [[webView resourceLoadDelegate] webView:webView resource:identifier didFinishLoadingFromDataSource:self];
548 [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didFinishLoadingFromDataSource:self];
551 - (void)_didReceiveData:(NSData *)data contentLength:(int)lengthReceived forResource:(id)identifier
553 WebView *webView = [self _webView];
555 [webView _incrementProgressForIdentifier:identifier data:data];
557 if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidReceiveContentLength)
558 [[webView resourceLoadDelegate] webView:webView resource:identifier didReceiveContentLength:(WebNSUInteger)lengthReceived fromDataSource:self];
560 [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didReceiveContentLength:(WebNSUInteger)lengthReceived fromDataSource:self];
563 - (void)_didReceiveResponse:(NSURLResponse *)r forResource:(id)identifier
565 WebView *webView = [self _webView];
567 [self _addResponse:r];
569 [webView _incrementProgressForIdentifier:identifier response:r];
571 if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidReceiveResponse)
572 [[webView resourceLoadDelegate] webView:webView resource:identifier didReceiveResponse:r fromDataSource:self];
574 [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didReceiveResponse:r fromDataSource:self];
577 - (void)_didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)currentWebChallenge forResource:(id)identifier
579 WebView *webView = [self _webView];
581 if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidCancelAuthenticationChallenge)
582 [[webView resourceLoadDelegate] webView:webView resource:identifier didCancelAuthenticationChallenge:currentWebChallenge fromDataSource:self];
584 [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didCancelAuthenticationChallenge:currentWebChallenge fromDataSource:self];
587 - (void)_didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)currentWebChallenge forResource:(id)identifier
589 WebView *webView = [self _webView];
591 if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidReceiveAuthenticationChallenge)
592 [[webView resourceLoadDelegate] webView:webView resource:identifier didReceiveAuthenticationChallenge:currentWebChallenge fromDataSource:self];
594 [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didReceiveAuthenticationChallenge:currentWebChallenge fromDataSource:self];
597 - (NSURLRequest *)_willSendRequest:(NSMutableURLRequest *)clientRequest forResource:(id)identifier redirectResponse:(NSURLResponse *)redirectResponse
599 WebView *webView = [self _webView];
601 [clientRequest _web_setHTTPUserAgent:[webView userAgentForURL:[clientRequest URL]]];
603 if ([webView _resourceLoadDelegateImplementations].delegateImplementsWillSendRequest)
604 return [[webView resourceLoadDelegate] webView:webView resource:identifier willSendRequest:clientRequest redirectResponse:redirectResponse fromDataSource:self];
606 return [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier willSendRequest:clientRequest redirectResponse:redirectResponse fromDataSource:self];
609 - (id)_identifierForInitialRequest:(NSURLRequest *)clientRequest
611 WebView *webView = [self _webView];
613 // The identifier is released after the last callback, rather than in dealloc
614 // to avoid potential cycles.
615 if ([webView _resourceLoadDelegateImplementations].delegateImplementsIdentifierForRequest)
616 return [[[webView resourceLoadDelegate] webView:webView identifierForInitialRequest:clientRequest fromDataSource:self] retain];
618 return [[[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView identifierForInitialRequest:clientRequest fromDataSource:self] retain];
621 - (WebResource *)_archivedSubresourceForURL:(NSURL *)URL
623 return [_private->unarchivingState archivedResourceForURL:URL];
626 - (void)_startLoading
628 [self _prepareForLoadStart];
630 if ([[_private->webFrame _frameLoader] isLoadingMainResource])
633 _private->loadingFromPageCache = NO;
636 id resourceLoadDelegate = [[self _webView] resourceLoadDelegate];
637 if ([resourceLoadDelegate respondsToSelector:@selector(webView:identifierForInitialRequest:fromDataSource:)])
638 identifier = [resourceLoadDelegate webView:[self _webView] identifierForInitialRequest:_private->originalRequest fromDataSource:self];
640 identifier = [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:[self _webView] identifierForInitialRequest:_private->originalRequest fromDataSource:self];
642 [[_private->webFrame _frameLoader] startLoadingMainResourceWithRequest:_private->request identifier:identifier];
645 - (void)_stopRecordingResponses
647 _private->stopRecordingResponses = YES;
650 - (double)_loadingStartedTime
652 return _private->loadingStartedTime;
655 - (void)_replaceSelectionWithArchive:(WebArchive *)archive selectReplacement:(BOOL)selectReplacement
657 DOMDocumentFragment *fragment = [self _documentFragmentWithArchive:archive];
659 [[self _bridge] replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:NO matchStyle:NO];
662 - (DOMDocumentFragment *)_documentFragmentWithArchive:(WebArchive *)archive
665 WebResource *mainResource = [archive mainResource];
667 NSString *MIMEType = [mainResource MIMEType];
668 if ([WebView canShowMIMETypeAsHTML:MIMEType]) {
669 NSString *markupString = [[NSString alloc] initWithData:[mainResource data] encoding:NSUTF8StringEncoding];
670 // FIXME: seems poor form to do this as a side effect of getting a document fragment
671 [self _addToUnarchiveState:archive];
672 DOMDocumentFragment *fragment = [[self _bridge] documentFragmentWithMarkupString:markupString baseURLString:[[mainResource URL] _web_originalDataAsString]];
673 [markupString release];
675 } else if ([[WebFrameBridge supportedImageResourceMIMETypes] containsObject:MIMEType]) {
676 return [self _documentFragmentWithImageResource:mainResource];
683 - (DOMDocumentFragment *)_documentFragmentWithImageResource:(WebResource *)resource
685 DOMElement *imageElement = [self _imageElementWithImageResource:resource];
688 DOMDocumentFragment *fragment = [[[self _bridge] DOMDocument] createDocumentFragment];
689 [fragment appendChild:imageElement];
693 - (DOMElement *)_imageElementWithImageResource:(WebResource *)resource
698 [self addSubresource:resource];
700 DOMElement *imageElement = [[[self _bridge] DOMDocument] createElement:@"img"];
702 // FIXME: calling _web_originalDataAsString on a file URL returns an absolute path. Workaround this.
703 NSURL *URL = [resource URL];
704 [imageElement setAttribute:@"src" :[URL isFileURL] ? [URL absoluteString] : [URL _web_originalDataAsString]];
711 return _private->pageTitle;
716 return _private->stopping;
719 - (void)_setWebFrame:(WebFrame *)frame
722 [_private->webFrame release];
723 _private->webFrame = frame;
725 [_private->loadState setFrameLoader:[frame _frameLoader]];
727 [self _defersCallbacksChanged];
728 // no need to do _defersCallbacksChanged for subframes since they too
729 // will be or have been told of their WebFrame
732 // May return nil if not initialized with a URL.
735 return [[self request] URL];
738 - (void)_loadFromPageCache:(NSDictionary *)pageCache
740 [self _prepareForLoadStart];
741 _private->loadingFromPageCache = YES;
742 _private->committed = TRUE;
743 [[self webFrame] _commitProvisionalLoad:pageCache];
746 - (WebArchive *)_popSubframeArchiveWithName:(NSString *)frameName
748 return [_private->unarchivingState popSubframeArchiveWithFrameName:frameName];
751 - (void)_setIsClientRedirect:(BOOL)flag
753 _private->isClientRedirect = flag;
756 - (void)_setURL:(NSURL *)URL
758 NSMutableURLRequest *newOriginalRequest = [_private->originalRequestCopy mutableCopy];
759 [_private->originalRequestCopy release];
760 [newOriginalRequest setURL:URL];
761 _private->originalRequestCopy = newOriginalRequest;
763 NSMutableURLRequest *newRequest = [_private->request mutableCopy];
764 [_private->request release];
765 [newRequest setURL:URL];
766 _private->request = newRequest;
769 - (void)_setLastCheckedRequest:(NSURLRequest *)request
771 NSURLRequest *oldRequest = _private->lastCheckedRequest;
772 _private->lastCheckedRequest = [request copy];
773 [oldRequest release];
776 - (void)_defersCallbacksChanged
778 BOOL defers = [[self _webView] defersCallbacks];
780 if (defers == _private->defersCallbacks) {
784 _private->defersCallbacks = defers;
785 [[_private->webFrame _frameLoader] setDefersCallbacks:defers];
788 - (NSURLRequest *)_lastCheckedRequest
790 // It's OK not to make a copy here because we know the caller
791 // isn't going to modify this request
792 return [[_private->lastCheckedRequest retain] autorelease];
795 // Cancels the data source's pending loads. Conceptually, a data source only loads
796 // one document at a time, but one document may have many related resources.
797 // _stopLoading will stop all loads initiated by the data source,
798 // but not loads initiated by child frames' data sources -- that's the WebFrame's job.
801 // Always attempt to stop the icon loader because it may still be loading after the data source
802 // is done loading and not stopping it can cause a world leak.
803 [[_private->webFrame _frameLoader] stopLoadingIcon];
805 // The same goes for the bridge/part, which may still be parsing.
806 if (_private->committed)
807 [[self _bridge] stopLoading];
809 if (![[_private->webFrame _frameLoader] isLoading])
814 _private->stopping = YES;
816 if ([[_private->webFrame _frameLoader] isLoadingMainResource]) {
817 // Stop the main resource loader and let it send the cancelled message.
818 [[_private->webFrame _frameLoader] cancelMainResourceLoad];
819 } else if ([[_private->webFrame _frameLoader] isLoadingSubresources]) {
820 // The main resource loader already finished loading. Set the cancelled error on the
821 // document and let the subresourceLoaders send individual cancelled messages below.
822 [self _setMainDocumentError:[self _cancelledError]];
824 // If there are no resource loaders, we need to manufacture a cancelled message.
825 // (A back/forward navigation has no resource loaders because its resources are cached.)
826 [self _mainReceivedError:[self _cancelledError] complete:YES];
829 [[_private->webFrame _frameLoader] stopLoadingSubresources];
830 [[_private->webFrame _frameLoader] stopLoadingPlugIns];
832 _private->stopping = NO;
837 - (WebFrameBridge *)_bridge
839 ASSERT(_private->committed);
840 return [[self webFrame] _bridge];
843 - (WebView *)_webView
845 return [_private->webFrame webView];
848 - (NSDictionary *)_triggeringAction
850 return [[_private->triggeringAction retain] autorelease];
853 - (void)_setTriggeringAction:(NSDictionary *)action
856 [_private->triggeringAction release];
857 _private->triggeringAction = action;
860 - (void)__adoptRequest:(NSMutableURLRequest *)request
862 if (request != _private->request){
863 [_private->request release];
864 _private->request = [request retain];
868 - (BOOL)_isDocumentHTML
870 NSString *MIMEType = [[self response] MIMEType];
871 return [WebView canShowMIMETypeAsHTML:MIMEType];
874 - (void)_stopLoadingWithError:(NSError *)error
876 [[_private->webFrame _frameLoader] stopLoadingWithError:error];
879 - (void)_setPrimaryLoadComplete:(BOOL)flag
881 _private->primaryLoadComplete = flag;
884 // FIXME: We could actually load it as soon as we've parsed
885 // the HEAD section, or determined there isn't one - but
886 // there's no callback for that.
889 if ([[_private->webFrame _frameLoader] isLoadingMainResource]) {
890 [_private->loadState setMainResourceData:[[_private->webFrame _frameLoader] mainResourceData]];
891 [[_private->webFrame _frameLoader] releaseMainResourceLoader];
894 if ([WebScriptDebugServer listenerCount])
895 [[WebScriptDebugServer sharedScriptDebugServer] webView:[[self webFrame] webView] didLoadMainResourceForDataSource:self];
899 - (NSArray *)_responses
901 return _private->responses;
904 - (BOOL)_loadingFromPageCache
906 return _private->loadingFromPageCache;
909 -(void)_makeRepresentation
911 Class repClass = [[self class] _representationClassForMIMEType:[[self response] MIMEType]];
913 // Check if the data source was already bound?
914 if (![[self representation] isKindOfClass:repClass]) {
915 id newRep = repClass != nil ? [[repClass alloc] init] : nil;
916 [self _setRepresentation:(id <WebDocumentRepresentation>)newRep];
920 [_private->representation setDataSource:self];
923 - (BOOL)_isClientRedirect
925 return _private->isClientRedirect;
929 - (NSURLRequest *)_originalRequest
931 return _private->originalRequestCopy;
934 - (NSURL *)_URLForHistory
936 // Return the URL to be used for history and B/F list.
937 // Returns nil for WebDataProtocol URLs that aren't alternates
938 // for unreachable URLs, because these can't be stored in history.
939 NSURL *URL = [_private->originalRequestCopy URL];
940 if ([WebDataProtocol _webIsDataProtocolURL:URL]) {
941 URL = [_private->originalRequestCopy _webDataRequestUnreachableURL];
944 return [URL _webkit_canonicalize];
947 - (void)_addToUnarchiveState:(WebArchive *)archive
949 if (!_private->unarchivingState)
950 _private->unarchivingState = [[WebUnarchivingState alloc] init];
951 [_private->unarchivingState addArchive:archive];
954 - (void)_setOverrideEncoding:(NSString *)overrideEncoding
956 NSString *copy = [overrideEncoding copy];
957 [_private->overrideEncoding release];
958 _private->overrideEncoding = copy;
961 - (void)_setIconURL:(NSURL *)URL
963 // Lower priority than typed icon, so ignore this if we already have an iconURL.
964 if (_private->iconURL == nil) {
965 [_private->iconURL release];
966 _private->iconURL = [URL retain];
970 - (void)_setIconURL:(NSURL *)URL withType:(NSString *)iconType
972 // FIXME: Should check to make sure the type is one we know how to handle.
973 [_private->iconURL release];
974 _private->iconURL = [URL retain];
977 - (NSString *)_overrideEncoding
979 return [[_private->overrideEncoding copy] autorelease];
982 - (void)_setTitle:(NSString *)title
988 trimmed = [title _webkit_stringByTrimmingWhitespace];
989 if ([trimmed length] == 0)
992 if (trimmed == nil) {
993 if (_private->pageTitle == nil)
996 if ([_private->pageTitle isEqualToString:trimmed])
1000 if (!trimmed || [trimmed length] == 0)
1003 [[self _webView] _willChangeValueForKey:_WebMainFrameTitleKey];
1004 [_private->pageTitle release];
1005 _private->pageTitle = [trimmed copy];
1006 [[self _webView] _didChangeValueForKey:_WebMainFrameTitleKey];
1008 // The title doesn't get communicated to the WebView until we are committed.
1009 if (_private->committed) {
1010 NSURL *URLForHistory = [self _URLForHistory];
1011 if (URLForHistory != nil) {
1012 WebHistoryItem *entry = [[WebHistory optionalSharedHistory] itemForURL:URLForHistory];
1013 [entry setTitle: _private->pageTitle];
1015 // Must update the entries in the back-forward list too. This must go through the WebFrame because
1016 // it has the right notion of the current b/f item.
1017 [[self webFrame] _setTitle:_private->pageTitle];
1019 [[self _webView] setMainFrameDocumentReady:YES]; // update observers with new DOMDocument
1020 [[[self _webView] _frameLoadDelegateForwarder] webView:[self _webView]
1021 didReceiveTitle:_private->pageTitle
1022 forFrame:[self webFrame]];
1029 @implementation WebDataSource
1031 -(id)initWithRequest:(NSURLRequest *)request
1033 self = [super init];
1038 _private = [[WebDataSourcePrivate alloc] init];
1040 _private->loadState = [[WebDocumentLoadState alloc] initWithRequest:request];
1042 _private->originalRequest = [request retain];
1043 _private->originalRequestCopy = [request copy];
1045 LOG(Loading, "creating datasource for %@", [request URL]);
1046 _private->request = [_private->originalRequest mutableCopy];
1047 _private->supportsMultipartContent = WKSupportsMultipartXMixedReplace(_private->request);
1049 ++WebDataSourceCount;
1056 ASSERT([[_private->webFrame _frameLoader] activeDataSource] != self || ![[_private->webFrame _frameLoader] isLoading]);
1058 --WebDataSourceCount;
1067 --WebDataSourceCount;
1074 return [_private->loadState mainResourceData];
1077 - (id <WebDocumentRepresentation>)representation
1079 return _private->representation;
1082 - (WebFrame *)webFrame
1084 return _private->webFrame;
1087 -(NSURLRequest *)initialRequest
1089 NSURLRequest *clientRequest = [_private->originalRequest _webDataRequestExternalRequest];
1091 clientRequest = _private->originalRequest;
1092 return clientRequest;
1095 -(NSMutableURLRequest *)request
1097 NSMutableURLRequest *clientRequest = [_private->request _webDataRequestExternalRequest];
1099 clientRequest = _private->request;
1100 return clientRequest;
1103 - (NSURLResponse *)response
1105 return _private->response;
1108 - (NSString *)textEncodingName
1110 NSString *textEncodingName = [self _overrideEncoding];
1112 if (!textEncodingName)
1113 textEncodingName = [[self response] textEncodingName];
1115 return textEncodingName;
1118 // Returns YES if there are any pending loads.
1121 // Once a frame has loaded, we no longer need to consider subresources,
1122 // but we still need to consider subframes.
1123 if ([[[self webFrame] _frameLoader] state] != WebFrameStateComplete) {
1124 if (!_private->primaryLoadComplete && [[_private->webFrame _frameLoader] isLoading])
1126 if ([[_private->webFrame _frameLoader] isLoadingSubresources])
1128 if (![[[self webFrame] _bridge] doneProcessingData])
1132 return [[self webFrame] _subframeIsLoading];
1135 // Returns nil or the page title.
1136 - (NSString *)pageTitle
1138 return [[self representation] title];
1141 - (NSURL *)unreachableURL
1143 return [_private->originalRequest _webDataRequestUnreachableURL];
1146 - (WebArchive *)webArchive
1148 // it makes no sense to grab a WebArchive from an uncommitted document.
1149 if (!_private->committed)
1152 return [WebArchiver archiveFrame:[self webFrame]];
1155 - (WebResource *)mainResource
1157 NSURLResponse *response = [self response];
1158 return [[[WebResource alloc] initWithData:[self data]
1160 MIMEType:[response MIMEType]
1161 textEncodingName:[response textEncodingName]
1162 frameName:[[self webFrame] name]] autorelease];
1165 - (NSArray *)subresources
1169 [[self _bridge] getAllResourceDatas:&datas andResponses:&responses];
1170 ASSERT([datas count] == [responses count]);
1172 NSMutableArray *subresources = [[NSMutableArray alloc] initWithCapacity:[datas count]];
1173 for (unsigned i = 0; i < [datas count]; ++i) {
1174 NSURLResponse *response = [responses objectAtIndex:i];
1175 [subresources addObject:[[[WebResource alloc] _initWithData:[datas objectAtIndex:i] URL:[response URL] response:response] autorelease]];
1178 return [subresources autorelease];
1181 - (WebResource *)subresourceForURL:(NSURL *)URL
1184 NSURLResponse *response;
1185 if (![[self _bridge] getData:&data andResponse:&response forURL:URL])
1188 return [[[WebResource alloc] _initWithData:data URL:URL response:response] autorelease];
1191 - (void)addSubresource:(WebResource *)subresource
1194 if (!_private->unarchivingState)
1195 _private->unarchivingState = [[WebUnarchivingState alloc] init];
1196 [_private->unarchivingState addResource:subresource];