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
152 ASSERT(![[webFrame _frameLoader] isLoading]);
156 [representation release];
158 [originalRequest release];
159 [originalRequestCopy release];
162 [mainDocumentError release];
164 [triggeringAction release];
165 [lastCheckedRequest release];
168 [unarchivingState release];
175 @interface WebDataSource (WebFileInternal)
178 @implementation WebDataSource (WebFileInternal)
180 - (void)_setRepresentation: (id<WebDocumentRepresentation>)representation
182 [_private->representation release];
183 _private->representation = [representation retain];
184 _private->representationFinishedLoading = NO;
189 // Don't load an icon if 1) this is not the main frame 2) we ended in error
190 // 3) they aren't saved by the DB
191 if ([self webFrame] != [[self _webView] mainFrame] || _private->mainDocumentError || ![[WebIconDatabase sharedIconDatabase] _isEnabled])
194 if (!_private->iconURL) {
195 // No icon URL from the LINK tag so try the server's root.
196 // This is only really a feature of http or https, so don't try this with other protocols.
197 NSString *scheme = [[self _URL] scheme];
198 if([scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"]){
199 _private->iconURL = [[[NSURL _web_URLWithDataAsString:@"/favicon.ico"
200 relativeToURL:[self _URL]] absoluteURL] retain];
204 if (_private->iconURL != nil) {
205 // If we have the icon already, we'll still see if we're manually reloading or if the icon is expired
206 // If so, kick off a reload of the icon
207 // If we don't have the icon already, kick off the initial load
208 if ([[WebIconDatabase sharedIconDatabase] _hasEntryForIconURL:[_private->iconURL _web_originalDataAsString]]) {
209 [[_private->webFrame _frameLoader] _updateIconDatabaseWithURL:_private->iconURL];
210 if ([[self webFrame] _loadType] == WebFrameLoadTypeReload || [[WebIconDatabase sharedIconDatabase] isIconExpiredForIconURL:[_private->iconURL _web_originalDataAsString]])
211 [[WebIconDatabase sharedIconDatabase] loadIconFromURL:[_private->iconURL _web_originalDataAsString]];
213 [[_private->webFrame _frameLoader] _notifyIconChanged:_private->iconURL];
215 NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:_private->iconURL];
216 [[self webFrame] _addExtraFieldsToRequest:request mainResource:YES alwaysFromRequest:NO];
217 [[_private->webFrame _frameLoader] loadIconWithRequest:request];
223 - (NSError *)_cancelledError
225 return [NSError _webKitErrorWithDomain:NSURLErrorDomain
226 code:NSURLErrorCancelled
230 - (void)_setMainDocumentError: (NSError *)error
233 [_private->mainDocumentError release];
234 _private->mainDocumentError = error;
236 if (!_private->representationFinishedLoading) {
237 _private->representationFinishedLoading = YES;
238 [[self representation] receivedError:error withDataSource:self];
244 [_private->mainDocumentError release];
245 _private->mainDocumentError = nil;
248 - (void)_prepareForLoadStart
250 ASSERT(![self _isStopping]);
251 [self _setPrimaryLoadComplete:NO];
252 ASSERT([self webFrame] != nil);
255 // Mark the start loading time.
256 _private->loadingStartedTime = CFAbsoluteTimeGetCurrent();
258 [[self _webView] _progressStarted:[self webFrame]];
259 [[self _webView] _didStartProvisionalLoadForFrame:[self webFrame]];
260 [[[self _webView] _frameLoadDelegateForwarder] webView:[self _webView]
261 didStartProvisionalLoadForFrame:[self webFrame]];
264 static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class class, NSArray *supportTypes)
266 NSEnumerator *enumerator = [supportTypes objectEnumerator];
267 ASSERT(enumerator != nil);
268 NSString *mime = nil;
269 while ((mime = [enumerator nextObject]) != nil) {
270 // Don't clobber previously-registered classes.
271 if ([allTypes objectForKey:mime] == nil)
272 [allTypes setObject:class forKey:mime];
276 + (Class)_representationClassForMIMEType:(NSString *)MIMEType
279 return [WebView _viewClass:nil andRepresentationClass:&repClass forMIMEType:MIMEType] ? repClass : nil;
282 - (void)_commitIfReady
284 if (_private->gotFirstByte && !_private->committed) {
285 _private->committed = TRUE;
286 [[self webFrame] _commitProvisionalLoad:nil];
290 - (void)_commitLoadWithData:(NSData *)data
292 // Both unloading the old page and parsing the new page may execute JavaScript which destroys the datasource
293 // by starting a new load, so retain temporarily.
295 [self _commitIfReady];
296 [[self representation] receivedData:data withDataSource:self];
297 [[[[self webFrame] frameView] documentView] dataSourceUpdated:self];
301 - (BOOL)_doesProgressiveLoadWithMIMEType:(NSString *)MIMEType
303 return [[self webFrame] _loadType] != WebFrameLoadTypeReplace || [MIMEType isEqualToString:@"text/html"];
306 - (void)_addResponse:(NSURLResponse *)r
308 if (!_private->stopRecordingResponses) {
309 if (!_private->responses)
310 _private->responses = [[NSMutableArray alloc] init];
311 [_private->responses addObject: r];
315 - (void)_revertToProvisionalState
317 [self _setRepresentation:nil];
318 [[_private->webFrame _frameLoader] setupForReplace];
319 _private->committed = NO;
324 @implementation WebDataSource (WebPrivate)
326 - (NSError *)_mainDocumentError
328 return _private->mainDocumentError;
331 - (void)_addSubframeArchives:(NSArray *)subframeArchives
333 NSEnumerator *enumerator = [subframeArchives objectEnumerator];
335 while ((archive = [enumerator nextObject]) != nil)
336 [self _addToUnarchiveState:archive];
339 - (NSFileWrapper *)_fileWrapperForURL:(NSURL *)URL
341 if ([URL isFileURL]) {
342 NSString *path = [[URL path] stringByResolvingSymlinksInPath];
343 return [[[NSFileWrapper alloc] initWithPath:path] autorelease];
346 WebResource *resource = [self subresourceForURL:URL];
348 return [resource _fileWrapperRepresentation];
351 NSCachedURLResponse *cachedResponse = [[self _webView] _cachedResponseForURL:URL];
352 if (cachedResponse) {
353 NSFileWrapper *wrapper = [[[NSFileWrapper alloc] initRegularFileWithContents:[cachedResponse data]] autorelease];
354 [wrapper setPreferredFilename:[[cachedResponse response] suggestedFilename]];
363 @implementation WebDataSource (WebInternal)
365 + (NSMutableDictionary *)_repTypesAllowImageTypeOmission:(BOOL)allowImageTypeOmission
367 static NSMutableDictionary *repTypes = nil;
368 static BOOL addedImageTypes = NO;
371 repTypes = [[NSMutableDictionary alloc] init];
372 addTypesFromClass(repTypes, [WebHTMLRepresentation class], [WebHTMLRepresentation supportedNonImageMIMETypes]);
374 // Since this is a "secret default" we don't both registering it.
375 BOOL omitPDFSupport = [[NSUserDefaults standardUserDefaults] boolForKey:@"WebKitOmitPDFSupport"];
377 addTypesFromClass(repTypes, [WebPDFRepresentation class], [WebPDFRepresentation supportedMIMETypes]);
380 if (!addedImageTypes && !allowImageTypeOmission) {
381 addTypesFromClass(repTypes, [WebHTMLRepresentation class], [WebHTMLRepresentation supportedImageMIMETypes]);
382 addedImageTypes = YES;
388 - (void)_decidePolicyForMIMEType:(NSString *)MIMEType decisionListener:(WebPolicyDecisionListener *)listener
390 WebView *wv = [self _webView];
391 [[wv _policyDelegateForwarder] webView:wv decidePolicyForMIMEType:MIMEType
392 request:[self request]
393 frame:[self webFrame]
394 decisionListener:listener];
397 - (void)_finishedLoading
399 _private->gotFirstByte = YES;
400 [self _commitIfReady];
402 _private->representationFinishedLoading = YES;
403 [[self representation] finishedLoadingWithDataSource:self];
404 [[self _bridge] end];
407 - (void)_setResponse:(NSURLResponse *)response
409 [_private->response release];
410 _private->response = [response retain];
413 - (void)_setRequest:(NSURLRequest *)request
415 ASSERT_ARG(request, request != _private->request);
417 // Replacing an unreachable URL with alternate content looks like a server-side
418 // redirect at this point, but we can replace a committed dataSource.
419 BOOL handlingUnreachableURL = [request _webDataRequestUnreachableURL] != nil;
420 if (handlingUnreachableURL) {
421 _private->committed = NO;
424 // We should never be getting a redirect callback after the data
425 // source is committed, except in the unreachable URL case. It
426 // would be a WebFoundation bug if it sent a redirect callback after commit.
427 ASSERT(!_private->committed);
429 NSURLRequest *oldRequest = _private->request;
431 _private->request = [request mutableCopy];
433 // Only send webView:didReceiveServerRedirectForProvisionalLoadForFrame: if URL changed.
434 // Also, don't send it when replacing unreachable URLs with alternate content.
435 if (!handlingUnreachableURL && ![[oldRequest URL] isEqual: [request URL]]) {
436 LOG(Redirect, "Server redirect to: %@", [request URL]);
437 [[[self _webView] _frameLoadDelegateForwarder] webView:[self _webView]
438 didReceiveServerRedirectForProvisionalLoadForFrame:[self webFrame]];
441 [oldRequest release];
444 - (void)_setupForReplaceByMIMEType:(NSString *)newMIMEType
446 if (!_private->gotFirstByte)
449 WebFrame *frame = [self webFrame];
450 NSString *oldMIMEType = [[self response] MIMEType];
452 if (![self _doesProgressiveLoadWithMIMEType:oldMIMEType]) {
453 [self _revertToProvisionalState];
454 [self _commitLoadWithData:[self data]];
457 _private->representationFinishedLoading = YES;
458 [[self representation] finishedLoadingWithDataSource:self];
459 [[self _bridge] end];
461 [frame _setLoadType:WebFrameLoadTypeReplace];
462 _private->gotFirstByte = NO;
464 if ([self _doesProgressiveLoadWithMIMEType:newMIMEType])
465 [self _revertToProvisionalState];
467 [[_private->webFrame _frameLoader] stopLoadingSubresources];
468 [[_private->webFrame _frameLoader] stopLoadingPlugIns];
469 [_private->unarchivingState release];
472 -(void)_receivedData:(NSData *)data
474 _private->gotFirstByte = YES;
476 if ([self _doesProgressiveLoadWithMIMEType:[[self response] MIMEType]])
477 [self _commitLoadWithData:data];
480 - (void)_receivedMainResourceError:(NSError *)error complete:(BOOL)isComplete
483 WebFrameBridge *bridge = [[self webFrame] _bridge];
485 // Retain the bridge because the stop may release the last reference to it.
489 // FIXME: Don't want to do this if an entirely new load is going, so should check
490 // that both data sources on the frame are either self or nil.
491 // Can't call [self _bridge] because we might not have commited yet
493 // FIXME: WebKitErrorPlugInWillHandleLoad is a workaround for the cancel we do to prevent loading plugin content twice. See <rdar://problem/4258008>
494 if ([error code] != NSURLErrorCancelled && [error code] != WebKitErrorPlugInWillHandleLoad)
495 [bridge handleFallbackContent];
500 [[self webFrame] _receivedMainResourceError:error];
501 [self _mainReceivedError:error complete:isComplete];
504 - (void)_mainReceivedError:(NSError *)error complete:(BOOL)isComplete
506 if (![self webFrame])
509 [self _setMainDocumentError:error];
512 [self _setPrimaryLoadComplete:YES];
513 [[self webFrame] _checkLoadComplete];
517 - (BOOL)_defersCallbacks
519 return _private->defersCallbacks;
522 - (void)_downloadWithLoadingConnection:(NSURLConnection *)connection request:(NSURLRequest *)request response:(NSURLResponse *)r proxy:(WKNSURLConnectionDelegateProxyPtr) proxy
524 [WebDownload _downloadWithLoadingConnection:connection
527 delegate:[[self _webView] downloadDelegate]
531 - (void)_didFailLoadingWithError:(NSError *)error forResource:(id)identifier
533 WebView *webView = [self _webView];
535 [webView _completeProgressForIdentifier:identifier];
538 [[webView _resourceLoadDelegateForwarder] webView:webView resource:identifier didFailLoadingWithError:error fromDataSource:self];
541 - (void)_didFinishLoadingForResource:(id)identifier
543 WebView *webView = [self _webView];
545 [webView _completeProgressForIdentifier:identifier];
547 if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidFinishLoadingFromDataSource)
548 [[webView resourceLoadDelegate] webView:webView resource:identifier didFinishLoadingFromDataSource:self];
550 [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didFinishLoadingFromDataSource:self];
553 - (void)_didReceiveData:(NSData *)data contentLength:(int)lengthReceived forResource:(id)identifier
555 WebView *webView = [self _webView];
557 [webView _incrementProgressForIdentifier:identifier data:data];
559 if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidReceiveContentLength)
560 [[webView resourceLoadDelegate] webView:webView resource:identifier didReceiveContentLength:(WebNSUInteger)lengthReceived fromDataSource:self];
562 [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didReceiveContentLength:(WebNSUInteger)lengthReceived fromDataSource:self];
565 - (void)_didReceiveResponse:(NSURLResponse *)r forResource:(id)identifier
567 WebView *webView = [self _webView];
569 [self _addResponse:r];
571 [webView _incrementProgressForIdentifier:identifier response:r];
573 if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidReceiveResponse)
574 [[webView resourceLoadDelegate] webView:webView resource:identifier didReceiveResponse:r fromDataSource:self];
576 [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didReceiveResponse:r fromDataSource:self];
579 - (void)_didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)currentWebChallenge forResource:(id)identifier
581 WebView *webView = [self _webView];
583 if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidCancelAuthenticationChallenge)
584 [[webView resourceLoadDelegate] webView:webView resource:identifier didCancelAuthenticationChallenge:currentWebChallenge fromDataSource:self];
586 [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didCancelAuthenticationChallenge:currentWebChallenge fromDataSource:self];
589 - (void)_didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)currentWebChallenge forResource:(id)identifier
591 WebView *webView = [self _webView];
593 if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidReceiveAuthenticationChallenge)
594 [[webView resourceLoadDelegate] webView:webView resource:identifier didReceiveAuthenticationChallenge:currentWebChallenge fromDataSource:self];
596 [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didReceiveAuthenticationChallenge:currentWebChallenge fromDataSource:self];
599 - (NSURLRequest *)_willSendRequest:(NSMutableURLRequest *)clientRequest forResource:(id)identifier redirectResponse:(NSURLResponse *)redirectResponse
601 WebView *webView = [self _webView];
603 [clientRequest _web_setHTTPUserAgent:[webView userAgentForURL:[clientRequest URL]]];
605 if ([webView _resourceLoadDelegateImplementations].delegateImplementsWillSendRequest)
606 return [[webView resourceLoadDelegate] webView:webView resource:identifier willSendRequest:clientRequest redirectResponse:redirectResponse fromDataSource:self];
608 return [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier willSendRequest:clientRequest redirectResponse:redirectResponse fromDataSource:self];
611 - (id)_identifierForInitialRequest:(NSURLRequest *)clientRequest
613 WebView *webView = [self _webView];
615 // The identifier is released after the last callback, rather than in dealloc
616 // to avoid potential cycles.
617 if ([webView _resourceLoadDelegateImplementations].delegateImplementsIdentifierForRequest)
618 return [[[webView resourceLoadDelegate] webView:webView identifierForInitialRequest:clientRequest fromDataSource:self] retain];
620 return [[[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView identifierForInitialRequest:clientRequest fromDataSource:self] retain];
623 - (WebResource *)_archivedSubresourceForURL:(NSURL *)URL
625 return [_private->unarchivingState archivedResourceForURL:URL];
628 - (void)_startLoading
630 [self _prepareForLoadStart];
632 if ([[_private->webFrame _frameLoader] isLoadingMainResource])
635 _private->loadingFromPageCache = NO;
638 id resourceLoadDelegate = [[self _webView] resourceLoadDelegate];
639 if ([resourceLoadDelegate respondsToSelector:@selector(webView:identifierForInitialRequest:fromDataSource:)])
640 identifier = [resourceLoadDelegate webView:[self _webView] identifierForInitialRequest:_private->originalRequest fromDataSource:self];
642 identifier = [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:[self _webView] identifierForInitialRequest:_private->originalRequest fromDataSource:self];
644 [[_private->webFrame _frameLoader] startLoadingMainResourceWithRequest:_private->request identifier:identifier];
647 - (void)_stopRecordingResponses
649 _private->stopRecordingResponses = YES;
652 - (double)_loadingStartedTime
654 return _private->loadingStartedTime;
657 - (void)_replaceSelectionWithArchive:(WebArchive *)archive selectReplacement:(BOOL)selectReplacement
659 DOMDocumentFragment *fragment = [self _documentFragmentWithArchive:archive];
661 [[self _bridge] replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:NO matchStyle:NO];
664 - (DOMDocumentFragment *)_documentFragmentWithArchive:(WebArchive *)archive
667 WebResource *mainResource = [archive mainResource];
669 NSString *MIMEType = [mainResource MIMEType];
670 if ([WebView canShowMIMETypeAsHTML:MIMEType]) {
671 NSString *markupString = [[NSString alloc] initWithData:[mainResource data] encoding:NSUTF8StringEncoding];
672 // FIXME: seems poor form to do this as a side effect of getting a document fragment
673 [self _addToUnarchiveState:archive];
674 DOMDocumentFragment *fragment = [[self _bridge] documentFragmentWithMarkupString:markupString baseURLString:[[mainResource URL] _web_originalDataAsString]];
675 [markupString release];
677 } else if ([[WebFrameBridge supportedImageResourceMIMETypes] containsObject:MIMEType]) {
678 return [self _documentFragmentWithImageResource:mainResource];
685 - (DOMDocumentFragment *)_documentFragmentWithImageResource:(WebResource *)resource
687 DOMElement *imageElement = [self _imageElementWithImageResource:resource];
690 DOMDocumentFragment *fragment = [[[self _bridge] DOMDocument] createDocumentFragment];
691 [fragment appendChild:imageElement];
695 - (DOMElement *)_imageElementWithImageResource:(WebResource *)resource
700 [self addSubresource:resource];
702 DOMElement *imageElement = [[[self _bridge] DOMDocument] createElement:@"img"];
704 // FIXME: calling _web_originalDataAsString on a file URL returns an absolute path. Workaround this.
705 NSURL *URL = [resource URL];
706 [imageElement setAttribute:@"src" :[URL isFileURL] ? [URL absoluteString] : [URL _web_originalDataAsString]];
713 return _private->pageTitle;
718 return _private->stopping;
721 - (void)_setWebFrame:(WebFrame *)frame
724 [_private->webFrame release];
725 _private->webFrame = frame;
727 [_private->loadState setFrameLoader:[frame _frameLoader]];
729 [self _defersCallbacksChanged];
730 // no need to do _defersCallbacksChanged for subframes since they too
731 // will be or have been told of their WebFrame
734 // May return nil if not initialized with a URL.
737 return [[self request] URL];
740 - (void)_loadFromPageCache:(NSDictionary *)pageCache
742 [self _prepareForLoadStart];
743 _private->loadingFromPageCache = YES;
744 _private->committed = TRUE;
745 [[self webFrame] _commitProvisionalLoad:pageCache];
748 - (WebArchive *)_popSubframeArchiveWithName:(NSString *)frameName
750 return [_private->unarchivingState popSubframeArchiveWithFrameName:frameName];
753 - (void)_setIsClientRedirect:(BOOL)flag
755 _private->isClientRedirect = flag;
758 - (void)_setURL:(NSURL *)URL
760 NSMutableURLRequest *newOriginalRequest = [_private->originalRequestCopy mutableCopy];
761 [_private->originalRequestCopy release];
762 [newOriginalRequest setURL:URL];
763 _private->originalRequestCopy = newOriginalRequest;
765 NSMutableURLRequest *newRequest = [_private->request mutableCopy];
766 [_private->request release];
767 [newRequest setURL:URL];
768 _private->request = newRequest;
771 - (void)_setLastCheckedRequest:(NSURLRequest *)request
773 NSURLRequest *oldRequest = _private->lastCheckedRequest;
774 _private->lastCheckedRequest = [request copy];
775 [oldRequest release];
778 - (void)_defersCallbacksChanged
780 BOOL defers = [[self _webView] defersCallbacks];
782 if (defers == _private->defersCallbacks) {
786 _private->defersCallbacks = defers;
787 [[_private->webFrame _frameLoader] setDefersCallbacks:defers];
790 - (NSURLRequest *)_lastCheckedRequest
792 // It's OK not to make a copy here because we know the caller
793 // isn't going to modify this request
794 return [[_private->lastCheckedRequest retain] autorelease];
797 // Cancels the data source's pending loads. Conceptually, a data source only loads
798 // one document at a time, but one document may have many related resources.
799 // _stopLoading will stop all loads initiated by the data source,
800 // but not loads initiated by child frames' data sources -- that's the WebFrame's job.
803 // Always attempt to stop the icon loader because it may still be loading after the data source
804 // is done loading and not stopping it can cause a world leak.
805 [[_private->webFrame _frameLoader] stopLoadingIcon];
807 // The same goes for the bridge/part, which may still be parsing.
808 if (_private->committed)
809 [[self _bridge] stopLoading];
811 if (![[_private->webFrame _frameLoader] isLoading])
816 _private->stopping = YES;
818 if ([[_private->webFrame _frameLoader] isLoadingMainResource]) {
819 // Stop the main resource loader and let it send the cancelled message.
820 [[_private->webFrame _frameLoader] cancelMainResourceLoad];
821 } else if ([[_private->webFrame _frameLoader] isLoadingSubresources]) {
822 // The main resource loader already finished loading. Set the cancelled error on the
823 // document and let the subresourceLoaders send individual cancelled messages below.
824 [self _setMainDocumentError:[self _cancelledError]];
826 // If there are no resource loaders, we need to manufacture a cancelled message.
827 // (A back/forward navigation has no resource loaders because its resources are cached.)
828 [self _mainReceivedError:[self _cancelledError] complete:YES];
831 [[_private->webFrame _frameLoader] stopLoadingSubresources];
832 [[_private->webFrame _frameLoader] stopLoadingPlugIns];
834 _private->stopping = NO;
839 - (WebFrameBridge *)_bridge
841 ASSERT(_private->committed);
842 return [[self webFrame] _bridge];
845 - (WebView *)_webView
847 return [_private->webFrame webView];
850 - (NSDictionary *)_triggeringAction
852 return [[_private->triggeringAction retain] autorelease];
855 - (void)_setTriggeringAction:(NSDictionary *)action
858 [_private->triggeringAction release];
859 _private->triggeringAction = action;
862 - (void)__adoptRequest:(NSMutableURLRequest *)request
864 if (request != _private->request){
865 [_private->request release];
866 _private->request = [request retain];
870 - (BOOL)_isDocumentHTML
872 NSString *MIMEType = [[self response] MIMEType];
873 return [WebView canShowMIMETypeAsHTML:MIMEType];
876 - (void)_stopLoadingWithError:(NSError *)error
878 [[_private->webFrame _frameLoader] stopLoadingWithError:error];
881 - (void)_setPrimaryLoadComplete:(BOOL)flag
883 _private->primaryLoadComplete = flag;
886 // FIXME: We could actually load it as soon as we've parsed
887 // the HEAD section, or determined there isn't one - but
888 // there's no callback for that.
891 if ([[_private->webFrame _frameLoader] isLoadingMainResource]) {
892 [_private->loadState setMainResourceData:[[_private->webFrame _frameLoader] mainResourceData]];
893 [[_private->webFrame _frameLoader] releaseMainResourceLoader];
896 if ([WebScriptDebugServer listenerCount])
897 [[WebScriptDebugServer sharedScriptDebugServer] webView:[[self webFrame] webView] didLoadMainResourceForDataSource:self];
901 - (NSArray *)_responses
903 return _private->responses;
906 - (BOOL)_loadingFromPageCache
908 return _private->loadingFromPageCache;
911 -(void)_makeRepresentation
913 Class repClass = [[self class] _representationClassForMIMEType:[[self response] MIMEType]];
915 // Check if the data source was already bound?
916 if (![[self representation] isKindOfClass:repClass]) {
917 id newRep = repClass != nil ? [[repClass alloc] init] : nil;
918 [self _setRepresentation:(id <WebDocumentRepresentation>)newRep];
922 [_private->representation setDataSource:self];
925 - (BOOL)_isClientRedirect
927 return _private->isClientRedirect;
931 - (NSURLRequest *)_originalRequest
933 return _private->originalRequestCopy;
936 - (NSURL *)_URLForHistory
938 // Return the URL to be used for history and B/F list.
939 // Returns nil for WebDataProtocol URLs that aren't alternates
940 // for unreachable URLs, because these can't be stored in history.
941 NSURL *URL = [_private->originalRequestCopy URL];
942 if ([WebDataProtocol _webIsDataProtocolURL:URL]) {
943 URL = [_private->originalRequestCopy _webDataRequestUnreachableURL];
946 return [URL _webkit_canonicalize];
949 - (void)_addToUnarchiveState:(WebArchive *)archive
951 if (!_private->unarchivingState)
952 _private->unarchivingState = [[WebUnarchivingState alloc] init];
953 [_private->unarchivingState addArchive:archive];
956 - (void)_setOverrideEncoding:(NSString *)overrideEncoding
958 NSString *copy = [overrideEncoding copy];
959 [_private->overrideEncoding release];
960 _private->overrideEncoding = copy;
963 - (void)_setIconURL:(NSURL *)URL
965 // Lower priority than typed icon, so ignore this if we already have an iconURL.
966 if (_private->iconURL == nil) {
967 [_private->iconURL release];
968 _private->iconURL = [URL retain];
972 - (void)_setIconURL:(NSURL *)URL withType:(NSString *)iconType
974 // FIXME: Should check to make sure the type is one we know how to handle.
975 [_private->iconURL release];
976 _private->iconURL = [URL retain];
979 - (NSString *)_overrideEncoding
981 return [[_private->overrideEncoding copy] autorelease];
984 - (void)_setTitle:(NSString *)title
990 trimmed = [title _webkit_stringByTrimmingWhitespace];
991 if ([trimmed length] == 0)
994 if (trimmed == nil) {
995 if (_private->pageTitle == nil)
998 if ([_private->pageTitle isEqualToString:trimmed])
1002 if (!trimmed || [trimmed length] == 0)
1005 [[self _webView] _willChangeValueForKey:_WebMainFrameTitleKey];
1006 [_private->pageTitle release];
1007 _private->pageTitle = [trimmed copy];
1008 [[self _webView] _didChangeValueForKey:_WebMainFrameTitleKey];
1010 // The title doesn't get communicated to the WebView until we are committed.
1011 if (_private->committed) {
1012 NSURL *URLForHistory = [self _URLForHistory];
1013 if (URLForHistory != nil) {
1014 WebHistoryItem *entry = [[WebHistory optionalSharedHistory] itemForURL:URLForHistory];
1015 [entry setTitle: _private->pageTitle];
1017 // Must update the entries in the back-forward list too. This must go through the WebFrame because
1018 // it has the right notion of the current b/f item.
1019 [[self webFrame] _setTitle:_private->pageTitle];
1021 [[self _webView] setMainFrameDocumentReady:YES]; // update observers with new DOMDocument
1022 [[[self _webView] _frameLoadDelegateForwarder] webView:[self _webView]
1023 didReceiveTitle:_private->pageTitle
1024 forFrame:[self webFrame]];
1031 @implementation WebDataSource
1033 -(id)initWithRequest:(NSURLRequest *)request
1035 self = [super init];
1040 _private = [[WebDataSourcePrivate alloc] init];
1042 _private->loadState = [[WebDocumentLoadState alloc] initWithRequest:request];
1044 _private->originalRequest = [request retain];
1045 _private->originalRequestCopy = [request copy];
1047 LOG(Loading, "creating datasource for %@", [request URL]);
1048 _private->request = [_private->originalRequest mutableCopy];
1049 _private->supportsMultipartContent = WKSupportsMultipartXMixedReplace(_private->request);
1051 ++WebDataSourceCount;
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];