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