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