71054e946a4f32aa04588b0fec3c10e5aa6ea9b5
[WebKit-https.git] / WebKit / WebView / WebDataSource.m
1 /*
2  * Copyright (C) 2005 Apple Computer, Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
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. 
16  *
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.
27  */
28
29 #import "WebDataSource.h"
30
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 "WebFrameLoadDelegate.h"
42 #import "WebFrameView.h"
43 #import "WebHTMLRepresentation.h"
44 #import "WebHTMLViewPrivate.h"
45 #import "WebHistory.h"
46 #import "WebHistoryItemPrivate.h"
47 #import "WebIconDatabasePrivate.h"
48 #import "WebIconLoader.h"
49 #import "WebKitErrorsPrivate.h"
50 #import "WebKitLogging.h"
51 #import "WebKitNSStringExtras.h"
52 #import "WebKitStatisticsPrivate.h"
53 #import "WebMainResourceLoader.h"
54 #import "WebNSObjectExtras.h"
55 #import "WebNSURLExtras.h"
56 #import "WebPDFRepresentation.h"
57 #import "WebPreferences.h"
58 #import "WebResourceLoadDelegate.h"
59 #import "WebResourcePrivate.h"
60 #import "WebUnarchivingState.h"
61 #import "WebViewInternal.h"
62 #import <Foundation/NSURLConnection.h>
63 #import <Foundation/NSURLRequest.h>
64 #import <JavaScriptCore/Assertions.h>
65 #import <WebKit/DOMHTML.h>
66 #import <WebKitSystemInterface.h>
67
68 @interface WebDataSourcePrivate : NSObject
69 {
70     @public
71     NSData *resourceData;
72     
73     id <WebDocumentRepresentation> representation;
74     
75     // A reference to actual request used to create the data source.
76     // This should only be used by the resourceLoadDelegate's
77     // identifierForInitialRequest:fromDatasource: method.  It is
78     // not guaranteed to remain unchanged, as requests are mutable.
79     NSURLRequest *originalRequest;
80     
81     // A copy of the original request used to create the data source.
82     // We have to copy the request because requests are mutable.
83     NSURLRequest *originalRequestCopy;
84     
85     // The 'working' request for this datasource.  It may be mutated
86     // several times from the original request to include additional
87     // headers, cookie information, canonicalization and redirects.
88     NSMutableURLRequest *request;
89     
90     NSURLResponse *response;
91     
92     // Client for main resource.
93     WebMainResourceLoader *mainResourceLoader;
94     
95     // Clients for other resources.
96     NSMutableArray *subresourceLoaders;
97     NSMutableArray *plugInStreamLoaders;
98     
99     // The time when the data source was told to start loading.
100     double loadingStartedTime;
101     
102     BOOL primaryLoadComplete;
103     
104     BOOL stopping;
105     
106     BOOL isClientRedirect;
107     
108     NSString *pageTitle;
109     
110     NSString *encoding;
111     NSString *overrideEncoding;
112     
113     // Error associated with main document.
114     NSError *mainDocumentError;
115     
116     BOOL loading; // self and webView are retained while loading
117     
118     BOOL gotFirstByte; // got first byte
119     BOOL committed; // This data source has been committed
120     BOOL representationFinishedLoading;
121     
122     BOOL defersCallbacks;
123     
124     NSURL *iconURL;
125     WebIconLoader *iconLoader;
126     
127     // The action that triggered loading of this data source -
128     // we keep this around for the benefit of the various policy
129     // handlers.
130     NSDictionary *triggeringAction;
131     
132     // The last request that we checked click policy for - kept around
133     // so we can avoid asking again needlessly.
134     NSURLRequest *lastCheckedRequest;
135     
136     // We retain all the received responses so we can play back the
137     // WebResourceLoadDelegate messages if the item is loaded from the
138     // page cache.
139     NSMutableArray *responses;
140     BOOL stopRecordingResponses;
141     
142     BOOL loadingFromPageCache;
143     
144     WebFrame *webFrame;
145     
146     NSMutableDictionary *subresources;
147     
148     WebUnarchivingState *unarchivingState;
149     
150     BOOL supportsMultipartContent;
151 }
152
153 @end
154
155 @implementation WebDataSourcePrivate 
156
157 - (void)dealloc
158 {
159     // The WebView is only retained while loading, but this object is also
160     // retained while loading, so no need to release here
161     ASSERT(!loading);
162
163     [resourceData release];
164     [representation release];
165     [request release];
166     [originalRequest release];
167     [originalRequestCopy release];
168     [mainResourceLoader release];
169     [subresourceLoaders release];
170     [plugInStreamLoaders release];
171     [pageTitle release];
172     [response release];
173     [mainDocumentError release];
174     [iconLoader release];
175     [iconURL release];
176     [triggeringAction release];
177     [lastCheckedRequest release];
178     [responses release];
179     [webFrame release];
180     [unarchivingState release];
181
182     [super dealloc];
183 }
184
185 @end
186
187 @implementation WebDataSource (WebPrivate)
188
189 - (NSFileWrapper *)_fileWrapperForURL:(NSURL *)URL
190 {
191     if ([URL isFileURL]) {
192         NSString *path = [[URL path] stringByResolvingSymlinksInPath];
193         return [[[NSFileWrapper alloc] initWithPath:path] autorelease];
194     }
195     
196     WebResource *resource = [self subresourceForURL:URL];
197     if (resource) {
198         return [resource _fileWrapperRepresentation];
199     }
200         
201     NSCachedURLResponse *cachedResponse = [[self _webView] _cachedResponseForURL:URL];
202     if (cachedResponse) {
203         NSFileWrapper *wrapper = [[[NSFileWrapper alloc] initRegularFileWithContents:[cachedResponse data]] autorelease];
204         [wrapper setPreferredFilename:[[cachedResponse response] suggestedFilename]];
205         return wrapper;
206     }
207     
208     return nil;
209 }
210
211 - (void)_addToUnarchiveState:(WebArchive *)archive
212 {
213     if (!_private->unarchivingState)
214         _private->unarchivingState = [[WebUnarchivingState alloc] init];
215     [_private->unarchivingState addArchive:archive];
216 }
217
218 - (WebArchive *)_popSubframeArchiveWithName:(NSString *)frameName
219 {
220     return [_private->unarchivingState popSubframeArchiveWithFrameName:frameName];
221 }
222
223 - (DOMElement *)_imageElementWithImageResource:(WebResource *)resource
224 {
225     if (!resource)
226         return 0;
227
228     [self addSubresource:resource];
229     
230     DOMElement *imageElement = [[[self _bridge] DOMDocument] createElement:@"img"];
231     
232     // FIXME: calling _web_originalDataAsString on a file URL returns an absolute path. Workaround this.
233     NSURL *URL = [resource URL];
234     [imageElement setAttribute:@"src" :[URL isFileURL] ? [URL absoluteString] : [URL _web_originalDataAsString]];
235     
236     return imageElement;
237 }
238
239 - (DOMDocumentFragment *)_documentFragmentWithImageResource:(WebResource *)resource
240 {
241     DOMElement *imageElement = [self _imageElementWithImageResource:resource];
242     if (!imageElement)
243         return 0;
244     DOMDocumentFragment *fragment = [[[self _bridge] DOMDocument] createDocumentFragment];
245     [fragment appendChild:imageElement];
246     return fragment;
247 }
248
249 - (DOMDocumentFragment *)_documentFragmentWithArchive:(WebArchive *)archive
250 {
251     ASSERT(archive);
252     WebResource *mainResource = [archive mainResource];
253     if (mainResource) {
254         NSString *MIMEType = [mainResource MIMEType];
255         if ([WebView canShowMIMETypeAsHTML:MIMEType]) {
256             NSString *markupString = [[NSString alloc] initWithData:[mainResource data] encoding:NSUTF8StringEncoding];
257             // FIXME: seems poor form to do this as a side effect of getting a document fragment
258             [self _addToUnarchiveState:archive];
259             DOMDocumentFragment *fragment = [[self _bridge] documentFragmentWithMarkupString:markupString baseURLString:[[mainResource URL] _web_originalDataAsString]];
260             [markupString release];
261             return fragment;
262         } else if ([[WebFrameBridge supportedImageResourceMIMETypes] containsObject:MIMEType]) {
263             return [self _documentFragmentWithImageResource:mainResource];
264
265         }
266     }
267     return nil;
268 }
269
270 - (void)_replaceSelectionWithArchive:(WebArchive *)archive selectReplacement:(BOOL)selectReplacement
271 {
272     DOMDocumentFragment *fragment = [self _documentFragmentWithArchive:archive];
273     if (fragment) {
274         [[self _bridge] replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:NO matchStyle:NO];
275     }
276 }
277
278 - (WebView *)_webView
279 {
280     return [_private->webFrame webView];
281 }
282
283 - (void)_setRepresentation: (id<WebDocumentRepresentation>)representation
284 {
285     [_private->representation release];
286     _private->representation = [representation retain];
287     _private->representationFinishedLoading = NO;
288 }
289
290 - (void)_setLoading:(BOOL)loading
291 {
292     _private->loading = loading;
293 }
294
295 - (void)_updateLoading
296 {
297     [self _setLoading:_private->mainResourceLoader || [_private->subresourceLoaders count]];
298 }
299
300 - (void)_setData:(NSData *)data
301 {
302     [data retain];
303     [_private->resourceData release];
304     _private->resourceData = data;
305 }
306
307 - (void)_updateIconDatabaseWithURL:(NSURL *)iconURL
308 {
309     ASSERT([[WebIconDatabase sharedIconDatabase] _isEnabled]);
310     
311     WebIconDatabase *iconDB = [WebIconDatabase sharedIconDatabase];
312     
313     // Bind the URL of the original request and the final URL to the icon URL.
314     [iconDB _setIconURL:[iconURL _web_originalDataAsString] forURL:[[self _URL] _web_originalDataAsString]];
315     [iconDB _setIconURL:[iconURL _web_originalDataAsString] forURL:[[[self _originalRequest] URL] _web_originalDataAsString]];
316     
317     
318     if ([self webFrame] == [[self _webView] mainFrame])
319         [[self _webView] _willChangeValueForKey:_WebMainFrameIconKey];
320     
321     NSImage *icon = [iconDB iconForURL:[[self _URL] _web_originalDataAsString] withSize:WebIconSmallSize];
322     [[[self _webView] _frameLoadDelegateForwarder] webView:[self _webView]
323                                             didReceiveIcon:icon
324                                                   forFrame:[self webFrame]];
325     
326     if ([self webFrame] == [[self _webView] mainFrame])
327         [[self _webView] _didChangeValueForKey:_WebMainFrameIconKey];
328 }
329
330 - (void)_loadIcon
331 {
332     // Don't load an icon if 1) this is not the main frame 2) we ended in error 3) we already did 4) they aren't save by the DB.
333     if ([self webFrame] != [[self _webView] mainFrame] || _private->mainDocumentError || _private->iconLoader ||
334         ![[WebIconDatabase sharedIconDatabase] _isEnabled]) {
335         return;
336     }
337     
338     if(!_private->iconURL){
339         // No icon URL from the LINK tag so try the server's root.
340         // This is only really a feature of http or https, so don't try this with other protocols.
341         NSString *scheme = [[self _URL] scheme];
342         if([scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"]){
343             _private->iconURL = [[[NSURL _web_URLWithDataAsString:@"/favicon.ico"
344                                                     relativeToURL:[self _URL]] absoluteURL] retain];
345         }
346     }
347     
348     if(_private->iconURL != nil){
349         if([[WebIconDatabase sharedIconDatabase] _hasIconForIconURL:[_private->iconURL _web_originalDataAsString]]){
350             [self _updateIconDatabaseWithURL:_private->iconURL];
351         }else{
352             ASSERT(!_private->iconLoader);
353             NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:_private->iconURL];
354             [[self webFrame] _addExtraFieldsToRequest:request mainResource:YES alwaysFromRequest:NO];
355             _private->iconLoader = [[WebIconLoader alloc] initWithRequest:request];
356             [request release];
357             [_private->iconLoader setDelegate:self];
358             [_private->iconLoader setDataSource:self];
359             [_private->iconLoader startLoading];
360         }
361     }
362 }
363
364 - (void)_setPrimaryLoadComplete: (BOOL)flag
365 {
366     _private->primaryLoadComplete = flag;
367     
368     if (flag) {
369         // FIXME: We could actually load it as soon as we've parsed
370         // the HEAD section, or determined there isn't one - but
371         // there's no callback for that.
372         [self _loadIcon];
373
374         if (_private->mainResourceLoader != nil) {
375             [self _setData:[_private->mainResourceLoader resourceData]];
376             [_private->mainResourceLoader release];
377             _private->mainResourceLoader = nil;
378         }
379         
380         [self _updateLoading];
381     }
382 }
383
384 - (NSError *)_cancelledError
385 {
386     return [NSError _webKitErrorWithDomain:NSURLErrorDomain
387                                       code:NSURLErrorCancelled
388                                        URL:[self _URL]];
389 }
390
391 // Cancels the data source's pending loads.  Conceptually, a data source only loads
392 // one document at a time, but one document may have many related resources. 
393 // _stopLoading will stop all loads initiated by the data source, 
394 // but not loads initiated by child frames' data sources -- that's the WebFrame's job.
395 - (void)_stopLoading
396 {
397     // Always attempt to stop the icon loader because it may still be loading after the data source
398     // is done loading and not stopping it can cause a world leak.
399     [_private->iconLoader stopLoading];
400
401     // The same goes for the bridge/part, which may still be parsing.
402     if (_private->committed)
403         [[self _bridge] stopLoading];
404
405     if (!_private->loading)
406         return;
407
408     [self retain];
409
410     _private->stopping = YES;
411     
412     if (_private->mainResourceLoader) {
413         // Stop the main resource loader and let it send the cancelled message.
414         [_private->mainResourceLoader cancel];
415     } else if ([_private->subresourceLoaders count] > 0) {
416         // The main resource loader already finished loading. Set the cancelled error on the 
417         // document and let the subresourceLoaders send individual cancelled messages below.
418         [self _setMainDocumentError:[self _cancelledError]];
419     } else {
420         // If there are no resource loaders, we need to manufacture a cancelled message.
421         // (A back/forward navigation has no resource loaders because its resources are cached.)
422         [self _mainReceivedError:[self _cancelledError] complete:YES];
423     }
424     
425     NSArray *loaders = [_private->subresourceLoaders copy];
426     [loaders makeObjectsPerformSelector:@selector(cancel)];
427     [loaders release];
428
429     _private->stopping = NO;
430     
431     [self release];
432 }
433
434 - (void)_clearErrors
435 {
436     [_private->mainDocumentError release];
437     _private->mainDocumentError = nil;
438 }
439
440 - (void)_prepareForLoadStart
441 {
442     ASSERT(![self _isStopping]);
443     [self _setPrimaryLoadComplete:NO];
444     ASSERT([self webFrame] != nil);
445     [self _clearErrors];
446     
447     // Mark the start loading time.
448     _private->loadingStartedTime = CFAbsoluteTimeGetCurrent();
449     
450     [self _setLoading:YES];
451     [[self _webView] _progressStarted:[self webFrame]];
452     [[self _webView] _didStartProvisionalLoadForFrame:[self webFrame]];
453     [[[self _webView] _frameLoadDelegateForwarder] webView:[self _webView]
454                                      didStartProvisionalLoadForFrame:[self webFrame]];
455 }
456
457 - (void)_loadFromPageCache:(NSDictionary *)pageCache
458 {
459     [self _prepareForLoadStart];
460     _private->loadingFromPageCache = YES;
461     _private->committed = TRUE;
462     [[self webFrame] _commitProvisionalLoad:pageCache];
463 }
464
465 - (void)_startLoading
466 {
467     [self _prepareForLoadStart];
468
469     if (_private->mainResourceLoader)
470         return;
471
472     _private->loadingFromPageCache = NO;
473         
474     id identifier;
475     id resourceLoadDelegate = [[self _webView] resourceLoadDelegate];
476     if ([resourceLoadDelegate respondsToSelector:@selector(webView:identifierForInitialRequest:fromDataSource:)])
477         identifier = [resourceLoadDelegate webView:[self _webView] identifierForInitialRequest:_private->originalRequest fromDataSource:self];
478     else
479         identifier = [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:[self _webView] identifierForInitialRequest:_private->originalRequest fromDataSource:self];
480     
481     _private->mainResourceLoader = [[WebMainResourceLoader alloc] initWithDataSource:self];
482     
483     [_private->mainResourceLoader setIdentifier: identifier];
484     [[self webFrame] _addExtraFieldsToRequest:_private->request mainResource:YES alwaysFromRequest:NO];
485     if (![_private->mainResourceLoader loadWithRequest:_private->request]) {
486         // FIXME: if this should really be caught, we should just ASSERT this doesn't happen;
487         // should it be caught by other parts of WebKit or other parts of the app?
488         LOG_ERROR("could not create WebResourceHandle for URL %@ -- should be caught by policy handler level", [_private->request URL]);
489         [_private->mainResourceLoader release];
490         _private->mainResourceLoader = nil;
491         [self _updateLoading];
492     }
493 }
494
495 - (void)_addSubresourceLoader:(WebLoader *)loader
496 {
497     if (_private->subresourceLoaders == nil) {
498         _private->subresourceLoaders = [[NSMutableArray alloc] init];
499     }
500     [_private->subresourceLoaders addObject:loader];
501     [self _setLoading:YES];
502 }
503
504 - (void)_removeSubresourceLoader:(WebLoader *)loader
505 {
506     [_private->subresourceLoaders removeObject:loader];
507     [self _updateLoading];
508 }
509
510 - (void)_addPlugInStreamLoader:(WebLoader *)loader
511 {
512     if (_private->plugInStreamLoaders == nil) {
513         _private->plugInStreamLoaders = [[NSMutableArray alloc] init];
514     }
515     [_private->plugInStreamLoaders addObject:loader];
516     [self _setLoading:YES];
517 }
518
519 - (void)_removePlugInStreamLoader:(WebLoader *)loader
520 {
521     [_private->plugInStreamLoaders removeObject:loader];
522     [self _updateLoading];
523 }
524
525 - (BOOL)_isStopping
526 {
527     return _private->stopping;
528 }
529
530 - (double)_loadingStartedTime
531 {
532     return _private->loadingStartedTime;
533 }
534
535 - (NSURL *)_URLForHistory
536 {
537     // Return the URL to be used for history and B/F list.
538     // Returns nil for WebDataProtocol URLs that aren't alternates 
539     // for unreachable URLs, because these can't be stored in history.
540     NSURL *URL = [_private->originalRequestCopy URL];
541     if ([WebDataProtocol _webIsDataProtocolURL:URL]) {
542         URL = [_private->originalRequestCopy _webDataRequestUnreachableURL];
543     }
544     
545     return [URL _webkit_canonicalize];
546 }
547
548 - (void)_setTitle:(NSString *)title
549 {
550     NSString *trimmed;
551     if (title == nil) {
552         trimmed = nil;
553     } else {
554         trimmed = [title _webkit_stringByTrimmingWhitespace];
555         if ([trimmed length] == 0)
556             trimmed = nil;
557     }
558     if (trimmed == nil) {
559         if (_private->pageTitle == nil)
560             return;
561     } else {
562         if ([_private->pageTitle isEqualToString:trimmed])
563             return;
564     }
565     
566     if (!trimmed || [trimmed length] == 0)
567         return;
568         
569     [[self _webView] _willChangeValueForKey:_WebMainFrameTitleKey];
570     [_private->pageTitle release];
571     _private->pageTitle = [trimmed copy];
572     [[self _webView] _didChangeValueForKey:_WebMainFrameTitleKey];
573     
574     // The title doesn't get communicated to the WebView until we are committed.
575     if (_private->committed) {
576         NSURL *URLForHistory = [self _URLForHistory];
577         if (URLForHistory != nil) {
578             WebHistoryItem *entry = [[WebHistory optionalSharedHistory] itemForURL:URLForHistory];
579             [entry setTitle: _private->pageTitle];
580             
581             // Must update the entries in the back-forward list too.  This must go through the WebFrame because
582             // it has the right notion of the current b/f item.
583             [[self webFrame] _setTitle:_private->pageTitle];
584             
585             [[self _webView] setMainFrameDocumentReady:YES];    // update observers with new DOMDocument
586             [[[self _webView] _frameLoadDelegateForwarder] webView:[self _webView]
587                                                      didReceiveTitle:_private->pageTitle
588                                                             forFrame:[self webFrame]];
589         }
590     }
591 }
592
593 - (NSString *)_title
594 {
595     return _private->pageTitle;
596 }
597
598 - (void)_setURL:(NSURL *)URL
599 {
600     NSMutableURLRequest *newOriginalRequest = [_private->originalRequestCopy mutableCopy];
601     [_private->originalRequestCopy release];
602     [newOriginalRequest setURL:URL];
603     _private->originalRequestCopy = newOriginalRequest;
604
605     NSMutableURLRequest *newRequest = [_private->request mutableCopy];
606     [_private->request release];
607     [newRequest setURL:URL];
608     _private->request = newRequest;
609 }
610
611 - (void)__adoptRequest:(NSMutableURLRequest *)request
612 {
613     if (request != _private->request){
614         [_private->request release];
615         _private->request = [request retain];
616     }
617 }
618
619 - (void)_setRequest:(NSURLRequest *)request
620 {
621     ASSERT_ARG(request, request != _private->request);
622     
623     // Replacing an unreachable URL with alternate content looks like a server-side
624     // redirect at this point, but we can replace a committed dataSource.
625     BOOL handlingUnreachableURL = [request _webDataRequestUnreachableURL] != nil;
626     if (handlingUnreachableURL) {
627         _private->committed = NO;
628     }
629     
630     // We should never be getting a redirect callback after the data
631     // source is committed, except in the unreachable URL case. It 
632     // would be a WebFoundation bug if it sent a redirect callback after commit.
633     ASSERT(!_private->committed);
634
635     NSURLRequest *oldRequest = _private->request;
636
637     _private->request = [request mutableCopy];
638
639     // Only send webView:didReceiveServerRedirectForProvisionalLoadForFrame: if URL changed.
640     // Also, don't send it when replacing unreachable URLs with alternate content.
641     if (!handlingUnreachableURL && ![[oldRequest URL] isEqual: [request URL]]) {
642         LOG(Redirect, "Server redirect to: %@", [request URL]);
643         [[[self _webView] _frameLoadDelegateForwarder] webView:[self _webView]
644                       didReceiveServerRedirectForProvisionalLoadForFrame:[self webFrame]];
645     }
646         
647     [oldRequest release];
648 }
649
650 - (void)_setResponse:(NSURLResponse *)response
651 {
652     [_private->response release];
653     _private->response = [response retain];
654 }
655
656 - (void)_setOverrideEncoding:(NSString *)overrideEncoding
657 {
658     NSString *copy = [overrideEncoding copy];
659     [_private->overrideEncoding release];
660     _private->overrideEncoding = copy;
661 }
662
663 - (NSString *)_overrideEncoding
664 {
665     return [[_private->overrideEncoding copy] autorelease];
666 }
667
668 - (void)_setIsClientRedirect:(BOOL)flag
669 {
670     _private->isClientRedirect = flag;
671 }
672
673 - (BOOL)_isClientRedirect
674 {
675     return _private->isClientRedirect;
676 }
677
678 - (void)_setMainDocumentError: (NSError *)error
679 {
680     [error retain];
681     [_private->mainDocumentError release];
682     _private->mainDocumentError = error;
683
684     if (!_private->representationFinishedLoading) {
685         _private->representationFinishedLoading = YES;
686         [[self representation] receivedError:error withDataSource:self];
687     }
688 }
689
690 static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class class, NSArray *supportTypes)
691 {
692     NSEnumerator *enumerator = [supportTypes objectEnumerator];
693     ASSERT(enumerator != nil);
694     NSString *mime = nil;
695     while ((mime = [enumerator nextObject]) != nil) {
696         // Don't clobber previously-registered classes.
697         if ([allTypes objectForKey:mime] == nil)
698             [allTypes setObject:class forKey:mime];
699     }
700 }
701
702 + (NSMutableDictionary *)_repTypesAllowImageTypeOmission:(BOOL)allowImageTypeOmission
703 {
704     static NSMutableDictionary *repTypes = nil;
705     static BOOL addedImageTypes = NO;
706     
707     if (!repTypes) {
708         repTypes = [[NSMutableDictionary alloc] init];
709         addTypesFromClass(repTypes, [WebHTMLRepresentation class], [WebHTMLRepresentation supportedNonImageMIMETypes]);
710
711         // Since this is a "secret default" we don't both registering it.
712         BOOL omitPDFSupport = [[NSUserDefaults standardUserDefaults] boolForKey:@"WebKitOmitPDFSupport"];
713         if (!omitPDFSupport)
714             addTypesFromClass(repTypes, [WebPDFRepresentation class], [WebPDFRepresentation supportedMIMETypes]);
715     }
716     
717     if (!addedImageTypes && !allowImageTypeOmission) {
718         addTypesFromClass(repTypes, [WebHTMLRepresentation class], [WebHTMLRepresentation supportedImageMIMETypes]);
719         addedImageTypes = YES;
720     }
721     
722     return repTypes;
723 }
724
725 + (Class)_representationClassForMIMEType:(NSString *)MIMEType
726 {
727     Class repClass;
728     return [WebView _viewClass:nil andRepresentationClass:&repClass forMIMEType:MIMEType] ? repClass : nil;
729 }
730
731 - (WebFrameBridge *)_bridge
732 {
733     ASSERT(_private->committed);
734     return [[self webFrame] _bridge];
735 }
736
737 - (void)_commitIfReady
738 {
739     if (_private->gotFirstByte && !_private->committed) {
740         _private->committed = TRUE;
741         [[self webFrame] _commitProvisionalLoad:nil];
742     }
743 }
744
745 -(void)_makeRepresentation
746 {
747     Class repClass = [[self class] _representationClassForMIMEType:[[self response] MIMEType]];
748     
749     // Check if the data source was already bound?
750     if (![[self representation] isKindOfClass:repClass]) {
751         id newRep = repClass != nil ? [[repClass alloc] init] : nil;
752         [self _setRepresentation:(id <WebDocumentRepresentation>)newRep];
753         [newRep release];
754     }
755
756     [_private->representation setDataSource:self];
757 }
758
759 - (void)_commitLoadWithData:(NSData *)data
760 {
761     // Both unloading the old page and parsing the new page may execute JavaScript which destroys the datasource
762     // by starting a new load, so retain temporarily.
763     [self retain];
764     [self _commitIfReady];
765     [[self representation] receivedData:data withDataSource:self];
766     [[[[self webFrame] frameView] documentView] dataSourceUpdated:self];
767     [self release];
768 }
769
770 - (BOOL)_doesProgressiveLoadWithMIMEType:(NSString *)MIMEType
771 {
772     return [[self webFrame] _loadType] != WebFrameLoadTypeReplace || [MIMEType isEqualToString:@"text/html"];
773 }
774
775 -(void)_receivedData:(NSData *)data
776 {    
777     _private->gotFirstByte = YES;
778     
779     if ([self _doesProgressiveLoadWithMIMEType:[[self response] MIMEType]])
780         [self _commitLoadWithData:data];
781 }
782
783 - (void)_finishedLoading
784 {
785     _private->gotFirstByte = YES;
786     [self _commitIfReady];
787
788     _private->representationFinishedLoading = YES;
789     [[self representation] finishedLoadingWithDataSource:self];
790     [[self _bridge] end];
791 }
792
793 - (void)_receivedMainResourceError:(NSError *)error complete:(BOOL)isComplete
794 {
795     WebFrameBridge *bridge = [[self webFrame] _bridge];
796     
797     // Retain the bridge because the stop may release the last reference to it.
798     [bridge retain];
799
800     if (isComplete) {
801         // FIXME: Don't want to do this if an entirely new load is going, so should check
802         // that both data sources on the frame are either self or nil.
803         // Can't call [self _bridge] because we might not have commited yet
804         [bridge stop];
805         // FIXME: WebKitErrorPlugInWillHandleLoad is a workaround for the cancel we do to prevent loading plugin content twice.  See <rdar://problem/4258008>
806         if ([error code] != NSURLErrorCancelled && [error code] != WebKitErrorPlugInWillHandleLoad)
807             [bridge handleFallbackContent];
808     }
809
810     [bridge release];
811
812     [[self webFrame] _receivedMainResourceError:error];
813     [self _mainReceivedError:error complete:isComplete];
814 }
815
816 - (void)_iconLoaderReceivedPageIcon:(WebIconLoader *)iconLoader
817 {
818     [self _updateIconDatabaseWithURL:[iconLoader URL]];
819 }
820
821 - (void)_setIconURL:(NSURL *)URL
822 {
823     // Lower priority than typed icon, so ignore this if we already have an iconURL.
824     if (_private->iconURL == nil) {
825         [_private->iconURL release];
826         _private->iconURL = [URL retain];
827     }
828 }
829
830 - (void)_setIconURL:(NSURL *)URL withType:(NSString *)iconType
831 {
832     // FIXME: Should check to make sure the type is one we know how to handle.
833     [_private->iconURL release];
834     _private->iconURL = [URL retain];
835 }
836
837 - (void)_defersCallbacksChanged
838 {
839     BOOL defers = [[self _webView] defersCallbacks];
840     
841     if (defers == _private->defersCallbacks) {
842         return;
843     }
844
845     _private->defersCallbacks = defers;
846     [_private->mainResourceLoader setDefersCallbacks:defers];
847
848     NSEnumerator *e = [_private->subresourceLoaders objectEnumerator];
849     WebLoader *loader;
850     while ((loader = [e nextObject])) {
851         [loader setDefersCallbacks:defers];
852     }
853     e = [_private->plugInStreamLoaders objectEnumerator];
854     while ((loader = [e nextObject])) {
855         [loader setDefersCallbacks:defers];
856     }
857 }
858
859 - (BOOL)_defersCallbacks
860 {
861     return _private->defersCallbacks;
862 }
863
864 - (id)_identifierForInitialRequest:(NSURLRequest *)clientRequest
865 {
866     WebView *webView = [self _webView];
867
868     // The identifier is released after the last callback, rather than in dealloc
869     // to avoid potential cycles.
870     if ([webView _resourceLoadDelegateImplementations].delegateImplementsIdentifierForRequest)
871         return [[[webView resourceLoadDelegate] webView:webView identifierForInitialRequest:clientRequest fromDataSource:self] retain];
872     else
873         return [[[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView identifierForInitialRequest:clientRequest fromDataSource:self] retain];
874 }
875
876 - (NSURLRequest *)_willSendRequest:(NSURLRequest *)clientRequest forResource:(id)identifier redirectResponse:(NSURLResponse *)redirectResponse
877 {
878     WebView *webView = [self _webView];
879
880     // If we have a special "applewebdata" scheme URL we send a fake request to the delegate.
881     if ([webView _resourceLoadDelegateImplementations].delegateImplementsWillSendRequest)
882         return [[webView resourceLoadDelegate] webView:webView resource:identifier willSendRequest:clientRequest redirectResponse:redirectResponse fromDataSource:self];
883     else
884         return [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier willSendRequest:clientRequest redirectResponse:redirectResponse fromDataSource:self];
885 }        
886
887 - (void)_didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)currentWebChallenge forResource:(id)identifier
888 {
889     WebView *webView = [self _webView];
890
891     if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidReceiveAuthenticationChallenge)
892         [[webView resourceLoadDelegate] webView:webView resource:identifier didReceiveAuthenticationChallenge:currentWebChallenge fromDataSource:self];
893     else
894         [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didReceiveAuthenticationChallenge:currentWebChallenge fromDataSource:self];
895 }
896
897
898 - (void)_didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)currentWebChallenge forResource:(id)identifier
899 {
900     WebView *webView = [self _webView];
901
902     if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidCancelAuthenticationChallenge)
903         [[webView resourceLoadDelegate] webView:webView resource:identifier didCancelAuthenticationChallenge:currentWebChallenge fromDataSource:self];
904     else
905         [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didCancelAuthenticationChallenge:currentWebChallenge fromDataSource:self];
906 }
907
908 - (void)_didReceiveResponse:(NSURLResponse *)r forResource:(id)identifier
909 {
910     WebView *webView = [self _webView];
911
912     [self _addResponse:r];
913
914     [webView _incrementProgressForIdentifier:identifier response:r];
915         
916     if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidReceiveResponse)
917         [[webView resourceLoadDelegate] webView:webView resource:identifier didReceiveResponse:r fromDataSource:self];
918     else
919         [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didReceiveResponse:r fromDataSource:self];
920 }
921
922 - (void)_didReceiveData:(NSData *)data contentLength:(int)lengthReceived forResource:(id)identifier
923 {
924     WebView *webView = [self _webView];
925
926     [webView _incrementProgressForIdentifier:identifier data:data];
927
928     if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidReceiveContentLength)
929         [[webView resourceLoadDelegate] webView:webView resource:identifier didReceiveContentLength:(WebNSUInteger)lengthReceived fromDataSource:self];
930     else
931         [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didReceiveContentLength:(WebNSUInteger)lengthReceived fromDataSource:self];
932 }
933
934
935 - (void)_didFinishLoadingForResource:(id)identifier
936 {
937     WebView *webView = [self _webView];
938
939     [webView _completeProgressForIdentifier:identifier];    
940     
941     if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidFinishLoadingFromDataSource)
942         [[webView resourceLoadDelegate] webView:webView resource:identifier didFinishLoadingFromDataSource:self];
943     else
944         [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didFinishLoadingFromDataSource:self];
945 }
946
947 - (void)_didFailLoadingWithError:(NSError *)error forResource:(id)identifier
948 {
949     WebView *webView = [self _webView];
950
951     [webView _completeProgressForIdentifier:identifier];
952
953     if (error)
954         [[webView _resourceLoadDelegateForwarder] webView:webView resource:identifier didFailLoadingWithError:error fromDataSource:self];
955 }
956
957 - (void)_downloadWithLoadingConnection:(NSURLConnection *)connection request:(NSURLRequest *)request response:(NSURLResponse *)r proxy:(WKNSURLConnectionDelegateProxyPtr) proxy
958 {
959     [WebDownload _downloadWithLoadingConnection:connection
960                  request:request
961                  response:r
962                  delegate:[[self _webView] downloadDelegate]
963                  proxy:proxy];
964 }
965
966 - (BOOL)_privateBrowsingEnabled
967 {
968     return [[[self _webView] preferences] privateBrowsingEnabled];
969 }    
970
971 - (NSURLRequest *)_originalRequest
972 {
973     return _private->originalRequestCopy;
974 }
975
976 - (void)_setTriggeringAction:(NSDictionary *)action
977 {
978     [action retain];
979     [_private->triggeringAction release];
980     _private->triggeringAction = action;
981 }
982
983 - (NSDictionary *)_triggeringAction
984 {
985     return [[_private->triggeringAction retain] autorelease];
986 }
987
988 - (NSURLRequest *)_lastCheckedRequest
989 {
990     // It's OK not to make a copy here because we know the caller
991     // isn't going to modify this request
992     return [[_private->lastCheckedRequest retain] autorelease];
993 }
994
995 - (void)_setLastCheckedRequest:(NSURLRequest *)request
996 {
997     NSURLRequest *oldRequest = _private->lastCheckedRequest;
998     _private->lastCheckedRequest = [request copy];
999     [oldRequest release];
1000 }
1001
1002 - (BOOL)_loadingFromPageCache
1003 {
1004     return _private->loadingFromPageCache;
1005 }
1006
1007 - (void)_addResponse:(NSURLResponse *)r
1008 {
1009     if (!_private->stopRecordingResponses) {
1010         if (!_private->responses)
1011             _private->responses = [[NSMutableArray alloc] init];
1012         [_private->responses addObject: r];
1013     }
1014 }
1015
1016 - (void)_stopRecordingResponses
1017 {
1018     _private->stopRecordingResponses = YES;
1019 }
1020
1021 - (NSArray *)_responses
1022 {
1023     return _private->responses;
1024 }
1025
1026 - (void)_stopLoadingWithError:(NSError *)error
1027 {
1028     [_private->mainResourceLoader cancelWithError:error];
1029 }
1030
1031 - (void)_setWebFrame:(WebFrame *)frame
1032 {
1033     [frame retain];
1034     [_private->webFrame release];
1035     _private->webFrame = frame;
1036
1037     [self _defersCallbacksChanged];
1038     // no need to do _defersCallbacksChanged for subframes since they too
1039     // will be or have been told of their WebFrame
1040 }
1041
1042 // May return nil if not initialized with a URL.
1043 - (NSURL *)_URL
1044 {
1045     return [[self request] URL];
1046 }
1047
1048 - (NSError *)_mainDocumentError
1049 {
1050     return _private->mainDocumentError;
1051 }
1052
1053 - (BOOL)_isDocumentHTML
1054 {
1055     NSString *MIMEType = [[self response] MIMEType];
1056     return [WebView canShowMIMETypeAsHTML:MIMEType];
1057 }
1058
1059 - (void)_revertToProvisionalState
1060 {
1061     [self _setRepresentation:nil];
1062     [[self webFrame] _setupForReplace];
1063     _private->committed = NO;
1064 }
1065
1066 - (void)_setupForReplaceByMIMEType:(NSString *)newMIMEType
1067 {
1068     if (!_private->gotFirstByte)
1069         return;
1070     
1071     WebFrame *frame = [self webFrame];
1072     NSString *oldMIMEType = [[self response] MIMEType];
1073     
1074     if (![self _doesProgressiveLoadWithMIMEType:oldMIMEType]) {
1075         [self _revertToProvisionalState];
1076         [self _commitLoadWithData:[self data]];
1077     }
1078     
1079     _private->representationFinishedLoading = YES;
1080     [[self representation] finishedLoadingWithDataSource:self];
1081     [[self _bridge] end];
1082
1083     [frame _setLoadType:WebFrameLoadTypeReplace];
1084     _private->gotFirstByte = NO;
1085
1086     if ([self _doesProgressiveLoadWithMIMEType:newMIMEType])
1087         [self _revertToProvisionalState];
1088
1089     [_private->subresourceLoaders makeObjectsPerformSelector:@selector(cancel)];
1090     [_private->subresourceLoaders removeAllObjects];
1091     [_private->plugInStreamLoaders makeObjectsPerformSelector:@selector(cancel)];
1092     [_private->plugInStreamLoaders removeAllObjects];
1093     [_private->unarchivingState release];
1094 }
1095
1096 - (WebResource *)_archivedSubresourceForURL:(NSURL *)URL
1097 {
1098     return [_private->unarchivingState archivedResourceForURL:URL];
1099 }
1100
1101 @end
1102
1103 @implementation WebDataSource
1104
1105 -(id)initWithRequest:(NSURLRequest *)request
1106 {
1107     self = [super init];
1108     if (!self) {
1109         return nil;
1110     }
1111     
1112     _private = [[WebDataSourcePrivate alloc] init];
1113     _private->originalRequest = [request retain];
1114     _private->originalRequestCopy = [request copy];
1115     
1116     LOG(Loading, "creating datasource for %@", [request URL]);
1117     _private->request = [_private->originalRequest mutableCopy];
1118     _private->supportsMultipartContent = WKSupportsMultipartXMixedReplace(_private->request);
1119
1120     ++WebDataSourceCount;
1121     
1122     return self;
1123 }
1124
1125 - (void)dealloc
1126 {
1127     --WebDataSourceCount;
1128     
1129     [_private->iconLoader setDelegate:nil];
1130     [_private release];
1131     
1132     [super dealloc];
1133 }
1134
1135 - (void)finalize
1136 {
1137     --WebDataSourceCount;
1138
1139     [_private->iconLoader setDelegate:nil];
1140
1141     [super finalize];
1142 }
1143
1144 - (NSData *)data
1145 {
1146     return _private->resourceData != nil ? _private->resourceData : [_private->mainResourceLoader resourceData];
1147 }
1148
1149 - (id <WebDocumentRepresentation>)representation
1150 {
1151     return _private->representation;
1152 }
1153
1154 - (WebFrame *)webFrame
1155 {
1156     return _private->webFrame;
1157 }
1158
1159 -(NSURLRequest *)initialRequest
1160 {
1161     NSURLRequest *clientRequest = [_private->originalRequest _webDataRequestExternalRequest];
1162     if (!clientRequest)
1163         clientRequest = _private->originalRequest;
1164     return clientRequest;
1165 }
1166
1167 -(NSMutableURLRequest *)request
1168 {
1169     NSMutableURLRequest *clientRequest = [_private->request _webDataRequestExternalRequest];
1170     if (!clientRequest)
1171         clientRequest = _private->request;
1172     return clientRequest;
1173 }
1174
1175 - (NSURLResponse *)response
1176 {
1177     return _private->response;
1178 }
1179
1180 - (NSString *)textEncodingName
1181 {
1182     NSString *textEncodingName = [self _overrideEncoding];
1183
1184     if (!textEncodingName) {
1185         textEncodingName = [[self response] textEncodingName];
1186     }
1187     return textEncodingName;
1188 }
1189
1190 // Returns YES if there are any pending loads.
1191 - (BOOL)isLoading
1192 {
1193     // Once a frame has loaded, we no longer need to consider subresources,
1194     // but we still need to consider subframes.
1195     if ([[self webFrame] _state] != WebFrameStateComplete) {
1196         if (!_private->primaryLoadComplete && _private->loading)
1197             return YES;
1198         if ([_private->subresourceLoaders count])
1199             return YES;
1200         if (![[[self webFrame] _bridge] doneProcessingData])
1201             return YES;
1202     }
1203
1204     return [[self webFrame] _subframeIsLoading];
1205 }
1206
1207 // Returns nil or the page title.
1208 - (NSString *)pageTitle
1209 {
1210     return [[self representation] title];
1211 }
1212
1213 - (NSURL *)unreachableURL
1214 {
1215     return [_private->originalRequest _webDataRequestUnreachableURL];
1216 }
1217
1218 - (WebArchive *)webArchive
1219 {
1220     // it makes no sense to grab a WebArchive from an uncommitted document.
1221     if (!_private->committed)
1222         return nil;
1223
1224     return [WebArchiver archiveFrame:[self webFrame]];
1225 }
1226
1227 - (WebResource *)mainResource
1228 {
1229     NSURLResponse *response = [self response];
1230     return [[[WebResource alloc] initWithData:[self data]
1231                                           URL:[response URL] 
1232                                      MIMEType:[response MIMEType]
1233                              textEncodingName:[response textEncodingName]
1234                                     frameName:[[self webFrame] name]] autorelease];
1235 }
1236
1237 - (NSArray *)subresources
1238 {
1239     NSArray *datas;
1240     NSArray *responses;
1241     [[self _bridge] getAllResourceDatas:&datas andResponses:&responses];
1242     ASSERT([datas count] == [responses count]);
1243
1244     NSMutableArray *subresources = [[NSMutableArray alloc] initWithCapacity:[datas count]];
1245     for (unsigned i = 0; i < [datas count]; ++i) {
1246         NSURLResponse *response = [responses objectAtIndex:i];
1247         [subresources addObject:[[[WebResource alloc] _initWithData:[datas objectAtIndex:i] URL:[response URL] response:response] autorelease]];
1248     }
1249
1250     return [subresources autorelease];
1251 }
1252
1253 - (WebResource *)subresourceForURL:(NSURL *)URL
1254 {
1255     NSData *data;
1256     NSURLResponse *response;
1257     if (![[self _bridge] getData:&data andResponse:&response forURL:URL])
1258         return nil;
1259
1260     return [[[WebResource alloc] _initWithData:data URL:URL response:response] autorelease];
1261 }
1262
1263 - (void)addSubresource:(WebResource *)subresource
1264 {
1265     if (subresource) {
1266         if (!_private->unarchivingState)
1267             _private->unarchivingState = [[WebUnarchivingState alloc] init];
1268         [_private->unarchivingState addResource:subresource];
1269     }
1270 }
1271
1272 - (void)_finishedLoadingResource
1273 {
1274     [[self webFrame] _checkLoadComplete];
1275 }
1276
1277 - (void)_mainReceivedBytesSoFar:(unsigned)bytesSoFar complete:(BOOL)isComplete
1278 {
1279     WebFrame *frame = [self webFrame];
1280     
1281     // The frame may be nil if a previously cancelled load is still making progress callbacks.
1282     if (frame == nil)
1283         return;
1284         
1285     // This resource has completed, so check if the load is complete for this frame and its ancestors
1286     if (isComplete){
1287         // If the load is complete, mark the primary load as done.  The primary load is the load
1288         // of the main document.  Other resources may still be arriving.
1289         [self _setPrimaryLoadComplete:YES];
1290         [frame _checkLoadComplete];
1291     }
1292 }
1293
1294 - (void)_receivedError:(NSError *)error
1295 {
1296     [[self webFrame] _checkLoadComplete];
1297 }
1298
1299 - (void)_mainReceivedError:(NSError *)error complete:(BOOL)isComplete
1300 {
1301     if (![self webFrame])
1302         return;
1303     
1304     [self _setMainDocumentError:error];
1305
1306     if (isComplete) {
1307         [self _setPrimaryLoadComplete:YES];
1308         [[self webFrame] _checkLoadComplete];
1309     }
1310 }
1311
1312 @end