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>
69 @interface WebDataSourcePrivate : NSObject
74 id <WebDocumentRepresentation> representation;
76 // A reference to actual request used to create the data source.
77 // This should only be used by the resourceLoadDelegate's
78 // identifierForInitialRequest:fromDatasource: method. It is
79 // not guaranteed to remain unchanged, as requests are mutable.
80 NSURLRequest *originalRequest;
82 // A copy of the original request used to create the data source.
83 // We have to copy the request because requests are mutable.
84 NSURLRequest *originalRequestCopy;
86 // The 'working' request for this datasource. It may be mutated
87 // several times from the original request to include additional
88 // headers, cookie information, canonicalization and redirects.
89 NSMutableURLRequest *request;
91 NSURLResponse *response;
93 // The time when the data source was told to start loading.
94 double loadingStartedTime;
96 BOOL primaryLoadComplete;
100 BOOL isClientRedirect;
105 NSString *overrideEncoding;
107 // Error associated with main document.
108 NSError *mainDocumentError;
110 BOOL gotFirstByte; // got first byte
111 BOOL committed; // This data source has been committed
112 BOOL representationFinishedLoading;
114 BOOL defersCallbacks;
118 // The action that triggered loading of this data source -
119 // we keep this around for the benefit of the various policy
121 NSDictionary *triggeringAction;
123 // The last request that we checked click policy for - kept around
124 // so we can avoid asking again needlessly.
125 NSURLRequest *lastCheckedRequest;
127 // We retain all the received responses so we can play back the
128 // WebResourceLoadDelegate messages if the item is loaded from the
130 NSMutableArray *responses;
131 BOOL stopRecordingResponses;
133 BOOL loadingFromPageCache;
137 NSMutableDictionary *subresources;
139 WebUnarchivingState *unarchivingState;
141 BOOL supportsMultipartContent;
146 @implementation WebDataSourcePrivate
150 ASSERT(![[webFrame _frameLoader] isLoading]);
152 [resourceData release];
153 [representation release];
155 [originalRequest release];
156 [originalRequestCopy release];
159 [mainDocumentError release];
161 [triggeringAction release];
162 [lastCheckedRequest release];
165 [unarchivingState release];
172 @interface WebDataSource (WebFileInternal)
175 @implementation WebDataSource (WebFileInternal)
177 - (void)_setRepresentation: (id<WebDocumentRepresentation>)representation
179 [_private->representation release];
180 _private->representation = [representation retain];
181 _private->representationFinishedLoading = NO;
184 - (void)_setData:(NSData *)data
187 [_private->resourceData release];
188 _private->resourceData = data;
193 // Don't load an icon if 1) this is not the main frame 2) we ended in error
194 // 3) they aren't saved by the DB
195 if ([self webFrame] != [[self _webView] mainFrame] || _private->mainDocumentError || ![[WebIconDatabase sharedIconDatabase] _isEnabled])
198 if (!_private->iconURL) {
199 // No icon URL from the LINK tag so try the server's root.
200 // This is only really a feature of http or https, so don't try this with other protocols.
201 NSString *scheme = [[self _URL] scheme];
202 if([scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"]){
203 _private->iconURL = [[[NSURL _web_URLWithDataAsString:@"/favicon.ico"
204 relativeToURL:[self _URL]] absoluteURL] retain];
208 if (_private->iconURL != nil) {
209 // If we have the icon already, we'll still see if we're manually reloading or if the icon is expired
210 // If so, kick off a reload of the icon
211 // If we don't have the icon already, kick off the initial load
212 if ([[WebIconDatabase sharedIconDatabase] _hasEntryForIconURL:[_private->iconURL _web_originalDataAsString]]) {
213 [[_private->webFrame _frameLoader] _updateIconDatabaseWithURL:_private->iconURL];
214 if ([[self webFrame] _loadType] == WebFrameLoadTypeReload || [[WebIconDatabase sharedIconDatabase] isIconExpiredForIconURL:[_private->iconURL _web_originalDataAsString]])
215 [[WebIconDatabase sharedIconDatabase] loadIconFromURL:[_private->iconURL _web_originalDataAsString]];
217 [[_private->webFrame _frameLoader] _notifyIconChanged:_private->iconURL];
219 NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:_private->iconURL];
220 [[self webFrame] _addExtraFieldsToRequest:request mainResource:YES alwaysFromRequest:NO];
221 [[_private->webFrame _frameLoader] loadIconWithRequest:request];
227 - (NSError *)_cancelledError
229 return [NSError _webKitErrorWithDomain:NSURLErrorDomain
230 code:NSURLErrorCancelled
234 - (void)_setMainDocumentError: (NSError *)error
237 [_private->mainDocumentError release];
238 _private->mainDocumentError = error;
240 if (!_private->representationFinishedLoading) {
241 _private->representationFinishedLoading = YES;
242 [[self representation] receivedError:error withDataSource:self];
248 [_private->mainDocumentError release];
249 _private->mainDocumentError = nil;
252 - (void)_prepareForLoadStart
254 ASSERT(![self _isStopping]);
255 [self _setPrimaryLoadComplete:NO];
256 ASSERT([self webFrame] != nil);
259 // Mark the start loading time.
260 _private->loadingStartedTime = CFAbsoluteTimeGetCurrent();
262 [[self _webView] _progressStarted:[self webFrame]];
263 [[self _webView] _didStartProvisionalLoadForFrame:[self webFrame]];
264 [[[self _webView] _frameLoadDelegateForwarder] webView:[self _webView]
265 didStartProvisionalLoadForFrame:[self webFrame]];
268 static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class class, NSArray *supportTypes)
270 NSEnumerator *enumerator = [supportTypes objectEnumerator];
271 ASSERT(enumerator != nil);
272 NSString *mime = nil;
273 while ((mime = [enumerator nextObject]) != nil) {
274 // Don't clobber previously-registered classes.
275 if ([allTypes objectForKey:mime] == nil)
276 [allTypes setObject:class forKey:mime];
280 + (Class)_representationClassForMIMEType:(NSString *)MIMEType
283 return [WebView _viewClass:nil andRepresentationClass:&repClass forMIMEType:MIMEType] ? repClass : nil;
286 - (void)_commitIfReady
288 if (_private->gotFirstByte && !_private->committed) {
289 _private->committed = TRUE;
290 [[self webFrame] _commitProvisionalLoad:nil];
294 - (void)_commitLoadWithData:(NSData *)data
296 // Both unloading the old page and parsing the new page may execute JavaScript which destroys the datasource
297 // by starting a new load, so retain temporarily.
299 [self _commitIfReady];
300 [[self representation] receivedData:data withDataSource:self];
301 [[[[self webFrame] frameView] documentView] dataSourceUpdated:self];
305 - (BOOL)_doesProgressiveLoadWithMIMEType:(NSString *)MIMEType
307 return [[self webFrame] _loadType] != WebFrameLoadTypeReplace || [MIMEType isEqualToString:@"text/html"];
310 - (void)_addResponse:(NSURLResponse *)r
312 if (!_private->stopRecordingResponses) {
313 if (!_private->responses)
314 _private->responses = [[NSMutableArray alloc] init];
315 [_private->responses addObject: r];
319 - (void)_revertToProvisionalState
321 [self _setRepresentation:nil];
322 [[_private->webFrame _frameLoader] setupForReplace];
323 _private->committed = NO;
328 @implementation WebDataSource (WebPrivate)
330 - (NSError *)_mainDocumentError
332 return _private->mainDocumentError;
335 - (void)_addSubframeArchives:(NSArray *)subframeArchives
337 NSEnumerator *enumerator = [subframeArchives objectEnumerator];
339 while ((archive = [enumerator nextObject]) != nil)
340 [self _addToUnarchiveState:archive];
343 - (NSFileWrapper *)_fileWrapperForURL:(NSURL *)URL
345 if ([URL isFileURL]) {
346 NSString *path = [[URL path] stringByResolvingSymlinksInPath];
347 return [[[NSFileWrapper alloc] initWithPath:path] autorelease];
350 WebResource *resource = [self subresourceForURL:URL];
352 return [resource _fileWrapperRepresentation];
355 NSCachedURLResponse *cachedResponse = [[self _webView] _cachedResponseForURL:URL];
356 if (cachedResponse) {
357 NSFileWrapper *wrapper = [[[NSFileWrapper alloc] initRegularFileWithContents:[cachedResponse data]] autorelease];
358 [wrapper setPreferredFilename:[[cachedResponse response] suggestedFilename]];
367 @implementation WebDataSource (WebInternal)
369 + (NSMutableDictionary *)_repTypesAllowImageTypeOmission:(BOOL)allowImageTypeOmission
371 static NSMutableDictionary *repTypes = nil;
372 static BOOL addedImageTypes = NO;
375 repTypes = [[NSMutableDictionary alloc] init];
376 addTypesFromClass(repTypes, [WebHTMLRepresentation class], [WebHTMLRepresentation supportedNonImageMIMETypes]);
378 // Since this is a "secret default" we don't both registering it.
379 BOOL omitPDFSupport = [[NSUserDefaults standardUserDefaults] boolForKey:@"WebKitOmitPDFSupport"];
381 addTypesFromClass(repTypes, [WebPDFRepresentation class], [WebPDFRepresentation supportedMIMETypes]);
384 if (!addedImageTypes && !allowImageTypeOmission) {
385 addTypesFromClass(repTypes, [WebHTMLRepresentation class], [WebHTMLRepresentation supportedImageMIMETypes]);
386 addedImageTypes = YES;
392 - (void)_decidePolicyForMIMEType:(NSString *)MIMEType decisionListener:(WebPolicyDecisionListener *)listener
394 WebView *wv = [self _webView];
395 [[wv _policyDelegateForwarder] webView:wv decidePolicyForMIMEType:MIMEType
396 request:[self request]
397 frame:[self webFrame]
398 decisionListener:listener];
401 - (void)_finishedLoading
403 _private->gotFirstByte = YES;
404 [self _commitIfReady];
406 _private->representationFinishedLoading = YES;
407 [[self representation] finishedLoadingWithDataSource:self];
408 [[self _bridge] end];
411 - (void)_setResponse:(NSURLResponse *)response
413 [_private->response release];
414 _private->response = [response retain];
417 - (void)_setRequest:(NSURLRequest *)request
419 ASSERT_ARG(request, request != _private->request);
421 // Replacing an unreachable URL with alternate content looks like a server-side
422 // redirect at this point, but we can replace a committed dataSource.
423 BOOL handlingUnreachableURL = [request _webDataRequestUnreachableURL] != nil;
424 if (handlingUnreachableURL) {
425 _private->committed = NO;
428 // We should never be getting a redirect callback after the data
429 // source is committed, except in the unreachable URL case. It
430 // would be a WebFoundation bug if it sent a redirect callback after commit.
431 ASSERT(!_private->committed);
433 NSURLRequest *oldRequest = _private->request;
435 _private->request = [request mutableCopy];
437 // Only send webView:didReceiveServerRedirectForProvisionalLoadForFrame: if URL changed.
438 // Also, don't send it when replacing unreachable URLs with alternate content.
439 if (!handlingUnreachableURL && ![[oldRequest URL] isEqual: [request URL]]) {
440 LOG(Redirect, "Server redirect to: %@", [request URL]);
441 [[[self _webView] _frameLoadDelegateForwarder] webView:[self _webView]
442 didReceiveServerRedirectForProvisionalLoadForFrame:[self webFrame]];
445 [oldRequest release];
448 - (void)_setupForReplaceByMIMEType:(NSString *)newMIMEType
450 if (!_private->gotFirstByte)
453 WebFrame *frame = [self webFrame];
454 NSString *oldMIMEType = [[self response] MIMEType];
456 if (![self _doesProgressiveLoadWithMIMEType:oldMIMEType]) {
457 [self _revertToProvisionalState];
458 [self _commitLoadWithData:[self data]];
461 _private->representationFinishedLoading = YES;
462 [[self representation] finishedLoadingWithDataSource:self];
463 [[self _bridge] end];
465 [frame _setLoadType:WebFrameLoadTypeReplace];
466 _private->gotFirstByte = NO;
468 if ([self _doesProgressiveLoadWithMIMEType:newMIMEType])
469 [self _revertToProvisionalState];
471 [[_private->webFrame _frameLoader] stopLoadingSubresources];
472 [[_private->webFrame _frameLoader] stopLoadingPlugIns];
473 [_private->unarchivingState release];
476 -(void)_receivedData:(NSData *)data
478 _private->gotFirstByte = YES;
480 if ([self _doesProgressiveLoadWithMIMEType:[[self response] MIMEType]])
481 [self _commitLoadWithData:data];
484 - (void)_receivedMainResourceError:(NSError *)error complete:(BOOL)isComplete
487 WebFrameBridge *bridge = [[self webFrame] _bridge];
489 // Retain the bridge because the stop may release the last reference to it.
493 // FIXME: Don't want to do this if an entirely new load is going, so should check
494 // that both data sources on the frame are either self or nil.
495 // Can't call [self _bridge] because we might not have commited yet
497 // FIXME: WebKitErrorPlugInWillHandleLoad is a workaround for the cancel we do to prevent loading plugin content twice. See <rdar://problem/4258008>
498 if ([error code] != NSURLErrorCancelled && [error code] != WebKitErrorPlugInWillHandleLoad)
499 [bridge handleFallbackContent];
504 [[self webFrame] _receivedMainResourceError:error];
505 [self _mainReceivedError:error complete:isComplete];
508 - (void)_mainReceivedError:(NSError *)error complete:(BOOL)isComplete
510 if (![self webFrame])
513 [self _setMainDocumentError:error];
516 [self _setPrimaryLoadComplete:YES];
517 [[self webFrame] _checkLoadComplete];
521 - (BOOL)_defersCallbacks
523 return _private->defersCallbacks;
526 - (void)_downloadWithLoadingConnection:(NSURLConnection *)connection request:(NSURLRequest *)request response:(NSURLResponse *)r proxy:(WKNSURLConnectionDelegateProxyPtr) proxy
528 [WebDownload _downloadWithLoadingConnection:connection
531 delegate:[[self _webView] downloadDelegate]
535 - (void)_didFailLoadingWithError:(NSError *)error forResource:(id)identifier
537 WebView *webView = [self _webView];
539 [webView _completeProgressForIdentifier:identifier];
542 [[webView _resourceLoadDelegateForwarder] webView:webView resource:identifier didFailLoadingWithError:error fromDataSource:self];
545 - (void)_didFinishLoadingForResource:(id)identifier
547 WebView *webView = [self _webView];
549 [webView _completeProgressForIdentifier:identifier];
551 if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidFinishLoadingFromDataSource)
552 [[webView resourceLoadDelegate] webView:webView resource:identifier didFinishLoadingFromDataSource:self];
554 [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didFinishLoadingFromDataSource:self];
557 - (void)_didReceiveData:(NSData *)data contentLength:(int)lengthReceived forResource:(id)identifier
559 WebView *webView = [self _webView];
561 [webView _incrementProgressForIdentifier:identifier data:data];
563 if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidReceiveContentLength)
564 [[webView resourceLoadDelegate] webView:webView resource:identifier didReceiveContentLength:(WebNSUInteger)lengthReceived fromDataSource:self];
566 [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didReceiveContentLength:(WebNSUInteger)lengthReceived fromDataSource:self];
569 - (void)_didReceiveResponse:(NSURLResponse *)r forResource:(id)identifier
571 WebView *webView = [self _webView];
573 [self _addResponse:r];
575 [webView _incrementProgressForIdentifier:identifier response:r];
577 if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidReceiveResponse)
578 [[webView resourceLoadDelegate] webView:webView resource:identifier didReceiveResponse:r fromDataSource:self];
580 [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didReceiveResponse:r fromDataSource:self];
583 - (void)_didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)currentWebChallenge forResource:(id)identifier
585 WebView *webView = [self _webView];
587 if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidCancelAuthenticationChallenge)
588 [[webView resourceLoadDelegate] webView:webView resource:identifier didCancelAuthenticationChallenge:currentWebChallenge fromDataSource:self];
590 [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didCancelAuthenticationChallenge:currentWebChallenge fromDataSource:self];
593 - (void)_didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)currentWebChallenge forResource:(id)identifier
595 WebView *webView = [self _webView];
597 if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidReceiveAuthenticationChallenge)
598 [[webView resourceLoadDelegate] webView:webView resource:identifier didReceiveAuthenticationChallenge:currentWebChallenge fromDataSource:self];
600 [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didReceiveAuthenticationChallenge:currentWebChallenge fromDataSource:self];
603 - (NSURLRequest *)_willSendRequest:(NSMutableURLRequest *)clientRequest forResource:(id)identifier redirectResponse:(NSURLResponse *)redirectResponse
605 WebView *webView = [self _webView];
607 [clientRequest _web_setHTTPUserAgent:[webView userAgentForURL:[clientRequest URL]]];
609 if ([webView _resourceLoadDelegateImplementations].delegateImplementsWillSendRequest)
610 return [[webView resourceLoadDelegate] webView:webView resource:identifier willSendRequest:clientRequest redirectResponse:redirectResponse fromDataSource:self];
612 return [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier willSendRequest:clientRequest redirectResponse:redirectResponse fromDataSource:self];
615 - (id)_identifierForInitialRequest:(NSURLRequest *)clientRequest
617 WebView *webView = [self _webView];
619 // The identifier is released after the last callback, rather than in dealloc
620 // to avoid potential cycles.
621 if ([webView _resourceLoadDelegateImplementations].delegateImplementsIdentifierForRequest)
622 return [[[webView resourceLoadDelegate] webView:webView identifierForInitialRequest:clientRequest fromDataSource:self] retain];
624 return [[[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView identifierForInitialRequest:clientRequest fromDataSource:self] retain];
627 - (WebResource *)_archivedSubresourceForURL:(NSURL *)URL
629 return [_private->unarchivingState archivedResourceForURL:URL];
632 - (void)_startLoading
634 [self _prepareForLoadStart];
636 if ([[_private->webFrame _frameLoader] isLoadingMainResource])
639 _private->loadingFromPageCache = NO;
642 id resourceLoadDelegate = [[self _webView] resourceLoadDelegate];
643 if ([resourceLoadDelegate respondsToSelector:@selector(webView:identifierForInitialRequest:fromDataSource:)])
644 identifier = [resourceLoadDelegate webView:[self _webView] identifierForInitialRequest:_private->originalRequest fromDataSource:self];
646 identifier = [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:[self _webView] identifierForInitialRequest:_private->originalRequest fromDataSource:self];
648 [[_private->webFrame _frameLoader] startLoadingMainResourceWithRequest:_private->request identifier:identifier];
651 - (void)_stopRecordingResponses
653 _private->stopRecordingResponses = YES;
656 - (double)_loadingStartedTime
658 return _private->loadingStartedTime;
661 - (void)_replaceSelectionWithArchive:(WebArchive *)archive selectReplacement:(BOOL)selectReplacement
663 DOMDocumentFragment *fragment = [self _documentFragmentWithArchive:archive];
665 [[self _bridge] replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:NO matchStyle:NO];
668 - (DOMDocumentFragment *)_documentFragmentWithArchive:(WebArchive *)archive
671 WebResource *mainResource = [archive mainResource];
673 NSString *MIMEType = [mainResource MIMEType];
674 if ([WebView canShowMIMETypeAsHTML:MIMEType]) {
675 NSString *markupString = [[NSString alloc] initWithData:[mainResource data] encoding:NSUTF8StringEncoding];
676 // FIXME: seems poor form to do this as a side effect of getting a document fragment
677 [self _addToUnarchiveState:archive];
678 DOMDocumentFragment *fragment = [[self _bridge] documentFragmentWithMarkupString:markupString baseURLString:[[mainResource URL] _web_originalDataAsString]];
679 [markupString release];
681 } else if ([[WebFrameBridge supportedImageResourceMIMETypes] containsObject:MIMEType]) {
682 return [self _documentFragmentWithImageResource:mainResource];
689 - (DOMDocumentFragment *)_documentFragmentWithImageResource:(WebResource *)resource
691 DOMElement *imageElement = [self _imageElementWithImageResource:resource];
694 DOMDocumentFragment *fragment = [[[self _bridge] DOMDocument] createDocumentFragment];
695 [fragment appendChild:imageElement];
699 - (DOMElement *)_imageElementWithImageResource:(WebResource *)resource
704 [self addSubresource:resource];
706 DOMElement *imageElement = [[[self _bridge] DOMDocument] createElement:@"img"];
708 // FIXME: calling _web_originalDataAsString on a file URL returns an absolute path. Workaround this.
709 NSURL *URL = [resource URL];
710 [imageElement setAttribute:@"src" :[URL isFileURL] ? [URL absoluteString] : [URL _web_originalDataAsString]];
717 return _private->pageTitle;
722 return _private->stopping;
725 - (void)_setWebFrame:(WebFrame *)frame
728 [_private->webFrame release];
729 _private->webFrame = frame;
731 [self _defersCallbacksChanged];
732 // no need to do _defersCallbacksChanged for subframes since they too
733 // will be or have been told of their WebFrame
736 // May return nil if not initialized with a URL.
739 return [[self request] URL];
742 - (void)_loadFromPageCache:(NSDictionary *)pageCache
744 [self _prepareForLoadStart];
745 _private->loadingFromPageCache = YES;
746 _private->committed = TRUE;
747 [[self webFrame] _commitProvisionalLoad:pageCache];
750 - (WebArchive *)_popSubframeArchiveWithName:(NSString *)frameName
752 return [_private->unarchivingState popSubframeArchiveWithFrameName:frameName];
755 - (void)_setIsClientRedirect:(BOOL)flag
757 _private->isClientRedirect = flag;
760 - (void)_setURL:(NSURL *)URL
762 NSMutableURLRequest *newOriginalRequest = [_private->originalRequestCopy mutableCopy];
763 [_private->originalRequestCopy release];
764 [newOriginalRequest setURL:URL];
765 _private->originalRequestCopy = newOriginalRequest;
767 NSMutableURLRequest *newRequest = [_private->request mutableCopy];
768 [_private->request release];
769 [newRequest setURL:URL];
770 _private->request = newRequest;
773 - (void)_setLastCheckedRequest:(NSURLRequest *)request
775 NSURLRequest *oldRequest = _private->lastCheckedRequest;
776 _private->lastCheckedRequest = [request copy];
777 [oldRequest release];
780 - (void)_defersCallbacksChanged
782 BOOL defers = [[self _webView] defersCallbacks];
784 if (defers == _private->defersCallbacks) {
788 _private->defersCallbacks = defers;
789 [[_private->webFrame _frameLoader] setDefersCallbacks:defers];
792 - (NSURLRequest *)_lastCheckedRequest
794 // It's OK not to make a copy here because we know the caller
795 // isn't going to modify this request
796 return [[_private->lastCheckedRequest retain] autorelease];
799 // Cancels the data source's pending loads. Conceptually, a data source only loads
800 // one document at a time, but one document may have many related resources.
801 // _stopLoading will stop all loads initiated by the data source,
802 // but not loads initiated by child frames' data sources -- that's the WebFrame's job.
805 // Always attempt to stop the icon loader because it may still be loading after the data source
806 // is done loading and not stopping it can cause a world leak.
807 [[_private->webFrame _frameLoader] stopLoadingIcon];
809 // The same goes for the bridge/part, which may still be parsing.
810 if (_private->committed)
811 [[self _bridge] stopLoading];
813 if (![[_private->webFrame _frameLoader] isLoading])
818 _private->stopping = YES;
820 if ([[_private->webFrame _frameLoader] isLoadingMainResource]) {
821 // Stop the main resource loader and let it send the cancelled message.
822 [[_private->webFrame _frameLoader] cancelMainResourceLoad];
823 } else if ([[_private->webFrame _frameLoader] isLoadingSubresources]) {
824 // The main resource loader already finished loading. Set the cancelled error on the
825 // document and let the subresourceLoaders send individual cancelled messages below.
826 [self _setMainDocumentError:[self _cancelledError]];
828 // If there are no resource loaders, we need to manufacture a cancelled message.
829 // (A back/forward navigation has no resource loaders because its resources are cached.)
830 [self _mainReceivedError:[self _cancelledError] complete:YES];
833 [[_private->webFrame _frameLoader] stopLoadingSubresources];
834 [[_private->webFrame _frameLoader] stopLoadingPlugIns];
836 _private->stopping = NO;
841 - (WebFrameBridge *)_bridge
843 ASSERT(_private->committed);
844 return [[self webFrame] _bridge];
847 - (WebView *)_webView
849 return [_private->webFrame webView];
852 - (NSDictionary *)_triggeringAction
854 return [[_private->triggeringAction retain] autorelease];
857 - (void)_setTriggeringAction:(NSDictionary *)action
860 [_private->triggeringAction release];
861 _private->triggeringAction = action;
864 - (void)__adoptRequest:(NSMutableURLRequest *)request
866 if (request != _private->request){
867 [_private->request release];
868 _private->request = [request retain];
872 - (BOOL)_isDocumentHTML
874 NSString *MIMEType = [[self response] MIMEType];
875 return [WebView canShowMIMETypeAsHTML:MIMEType];
878 - (void)_stopLoadingWithError:(NSError *)error
880 [[_private->webFrame _frameLoader] stopLoadingWithError:error];
883 - (void)_setPrimaryLoadComplete:(BOOL)flag
885 _private->primaryLoadComplete = flag;
888 // FIXME: We could actually load it as soon as we've parsed
889 // the HEAD section, or determined there isn't one - but
890 // there's no callback for that.
893 if ([[_private->webFrame _frameLoader] isLoadingMainResource]) {
894 [self _setData:[[_private->webFrame _frameLoader] mainResourceData]];
895 [[_private->webFrame _frameLoader] releaseMainResourceLoader];
898 if ([WebScriptDebugServer listenerCount])
899 [[WebScriptDebugServer sharedScriptDebugServer] webView:[[self webFrame] webView] didLoadMainResourceForDataSource:self];
903 - (NSArray *)_responses
905 return _private->responses;
908 - (BOOL)_loadingFromPageCache
910 return _private->loadingFromPageCache;
913 -(void)_makeRepresentation
915 Class repClass = [[self class] _representationClassForMIMEType:[[self response] MIMEType]];
917 // Check if the data source was already bound?
918 if (![[self representation] isKindOfClass:repClass]) {
919 id newRep = repClass != nil ? [[repClass alloc] init] : nil;
920 [self _setRepresentation:(id <WebDocumentRepresentation>)newRep];
924 [_private->representation setDataSource:self];
927 - (BOOL)_isClientRedirect
929 return _private->isClientRedirect;
933 - (NSURLRequest *)_originalRequest
935 return _private->originalRequestCopy;
938 - (NSURL *)_URLForHistory
940 // Return the URL to be used for history and B/F list.
941 // Returns nil for WebDataProtocol URLs that aren't alternates
942 // for unreachable URLs, because these can't be stored in history.
943 NSURL *URL = [_private->originalRequestCopy URL];
944 if ([WebDataProtocol _webIsDataProtocolURL:URL]) {
945 URL = [_private->originalRequestCopy _webDataRequestUnreachableURL];
948 return [URL _webkit_canonicalize];
951 - (void)_addToUnarchiveState:(WebArchive *)archive
953 if (!_private->unarchivingState)
954 _private->unarchivingState = [[WebUnarchivingState alloc] init];
955 [_private->unarchivingState addArchive:archive];
958 - (void)_setOverrideEncoding:(NSString *)overrideEncoding
960 NSString *copy = [overrideEncoding copy];
961 [_private->overrideEncoding release];
962 _private->overrideEncoding = copy;
965 - (void)_setIconURL:(NSURL *)URL
967 // Lower priority than typed icon, so ignore this if we already have an iconURL.
968 if (_private->iconURL == nil) {
969 [_private->iconURL release];
970 _private->iconURL = [URL retain];
974 - (void)_setIconURL:(NSURL *)URL withType:(NSString *)iconType
976 // FIXME: Should check to make sure the type is one we know how to handle.
977 [_private->iconURL release];
978 _private->iconURL = [URL retain];
981 - (NSString *)_overrideEncoding
983 return [[_private->overrideEncoding copy] autorelease];
986 - (void)_setTitle:(NSString *)title
992 trimmed = [title _webkit_stringByTrimmingWhitespace];
993 if ([trimmed length] == 0)
996 if (trimmed == nil) {
997 if (_private->pageTitle == nil)
1000 if ([_private->pageTitle isEqualToString:trimmed])
1004 if (!trimmed || [trimmed length] == 0)
1007 [[self _webView] _willChangeValueForKey:_WebMainFrameTitleKey];
1008 [_private->pageTitle release];
1009 _private->pageTitle = [trimmed copy];
1010 [[self _webView] _didChangeValueForKey:_WebMainFrameTitleKey];
1012 // The title doesn't get communicated to the WebView until we are committed.
1013 if (_private->committed) {
1014 NSURL *URLForHistory = [self _URLForHistory];
1015 if (URLForHistory != nil) {
1016 WebHistoryItem *entry = [[WebHistory optionalSharedHistory] itemForURL:URLForHistory];
1017 [entry setTitle: _private->pageTitle];
1019 // Must update the entries in the back-forward list too. This must go through the WebFrame because
1020 // it has the right notion of the current b/f item.
1021 [[self webFrame] _setTitle:_private->pageTitle];
1023 [[self _webView] setMainFrameDocumentReady:YES]; // update observers with new DOMDocument
1024 [[[self _webView] _frameLoadDelegateForwarder] webView:[self _webView]
1025 didReceiveTitle:_private->pageTitle
1026 forFrame:[self webFrame]];
1033 @implementation WebDataSource
1035 -(id)initWithRequest:(NSURLRequest *)request
1037 self = [super init];
1042 _private = [[WebDataSourcePrivate alloc] init];
1043 _private->originalRequest = [request retain];
1044 _private->originalRequestCopy = [request copy];
1046 LOG(Loading, "creating datasource for %@", [request URL]);
1047 _private->request = [_private->originalRequest mutableCopy];
1048 _private->supportsMultipartContent = WKSupportsMultipartXMixedReplace(_private->request);
1050 ++WebDataSourceCount;
1057 --WebDataSourceCount;
1066 --WebDataSourceCount;
1073 return _private->resourceData != nil ? _private->resourceData : [[_private->webFrame _frameLoader] mainResourceData];
1076 - (id <WebDocumentRepresentation>)representation
1078 return _private->representation;
1081 - (WebFrame *)webFrame
1083 return _private->webFrame;
1086 -(NSURLRequest *)initialRequest
1088 NSURLRequest *clientRequest = [_private->originalRequest _webDataRequestExternalRequest];
1090 clientRequest = _private->originalRequest;
1091 return clientRequest;
1094 -(NSMutableURLRequest *)request
1096 NSMutableURLRequest *clientRequest = [_private->request _webDataRequestExternalRequest];
1098 clientRequest = _private->request;
1099 return clientRequest;
1102 - (NSURLResponse *)response
1104 return _private->response;
1107 - (NSString *)textEncodingName
1109 NSString *textEncodingName = [self _overrideEncoding];
1111 if (!textEncodingName)
1112 textEncodingName = [[self response] textEncodingName];
1114 return textEncodingName;
1117 // Returns YES if there are any pending loads.
1120 // Once a frame has loaded, we no longer need to consider subresources,
1121 // but we still need to consider subframes.
1122 if ([[[self webFrame] _frameLoader] state] != WebFrameStateComplete) {
1123 if (!_private->primaryLoadComplete && [[_private->webFrame _frameLoader] isLoading])
1125 if ([[_private->webFrame _frameLoader] isLoadingSubresources])
1127 if (![[[self webFrame] _bridge] doneProcessingData])
1131 return [[self webFrame] _subframeIsLoading];
1134 // Returns nil or the page title.
1135 - (NSString *)pageTitle
1137 return [[self representation] title];
1140 - (NSURL *)unreachableURL
1142 return [_private->originalRequest _webDataRequestUnreachableURL];
1145 - (WebArchive *)webArchive
1147 // it makes no sense to grab a WebArchive from an uncommitted document.
1148 if (!_private->committed)
1151 return [WebArchiver archiveFrame:[self webFrame]];
1154 - (WebResource *)mainResource
1156 NSURLResponse *response = [self response];
1157 return [[[WebResource alloc] initWithData:[self data]
1159 MIMEType:[response MIMEType]
1160 textEncodingName:[response textEncodingName]
1161 frameName:[[self webFrame] name]] autorelease];
1164 - (NSArray *)subresources
1168 [[self _bridge] getAllResourceDatas:&datas andResponses:&responses];
1169 ASSERT([datas count] == [responses count]);
1171 NSMutableArray *subresources = [[NSMutableArray alloc] initWithCapacity:[datas count]];
1172 for (unsigned i = 0; i < [datas count]; ++i) {
1173 NSURLResponse *response = [responses objectAtIndex:i];
1174 [subresources addObject:[[[WebResource alloc] _initWithData:[datas objectAtIndex:i] URL:[response URL] response:response] autorelease]];
1177 return [subresources autorelease];
1180 - (WebResource *)subresourceForURL:(NSURL *)URL
1183 NSURLResponse *response;
1184 if (![[self _bridge] getData:&data andResponse:&response forURL:URL])
1187 return [[[WebResource alloc] _initWithData:data URL:URL response:response] autorelease];
1190 - (void)addSubresource:(WebResource *)subresource
1193 if (!_private->unarchivingState)
1194 _private->unarchivingState = [[WebUnarchivingState alloc] init];
1195 [_private->unarchivingState addResource:subresource];