f2e6c251d1c8863b0eca45db261b3417fb5d2dfd
[WebKit-https.git] / WebKit / WebView.subproj / WebDataSource.m
1 /*      
2         WebDataSource.m
3         Copyright 2001, 2002, Apple, Inc. All rights reserved.
4 */
5
6 #import <WebKit/WebDataSourcePrivate.h>
7
8 #import <WebKit/DOMHTML.h>
9 #import <WebKit/WebAssertions.h>
10 #import <WebKit/WebArchive.h>
11 #import <WebKit/WebBridge.h>
12 #import <WebKit/WebDataProtocol.h>
13 #import <WebKit/WebDefaultResourceLoadDelegate.h>
14 #import <WebKit/WebDocument.h>
15 #import <WebKit/WebDOMOperationsPrivate.h>
16 #import <WebKit/WebException.h>
17 #import <WebKit/WebFrameLoadDelegate.h>
18 #import <WebKit/WebFramePrivate.h>
19 #import <WebKit/WebFrameViewPrivate.h>
20 #import <WebKit/WebHistory.h>
21 #import <WebKit/WebHistoryItemPrivate.h>
22 #import <WebKit/WebHTMLRepresentation.h>
23 #import <WebKit/WebHTMLViewPrivate.h>
24 #import <WebKit/WebIconDatabasePrivate.h>
25 #import <WebKit/WebIconLoader.h>
26 #import <WebKit/WebImageRendererFactory.h>
27 #import <WebKit/WebImageRepresentation.h>
28 #import <WebKit/WebImageView.h>
29 #import <WebKit/WebKitErrorsPrivate.h>
30 #import <WebKit/WebKitLogging.h>
31 #import <WebKit/WebKitStatisticsPrivate.h>
32 #import <WebKit/WebMainResourceClient.h>
33 #import <WebKit/WebNSObjectExtras.h>
34 #import <WebKit/WebNSURLExtras.h>
35 // Assume we'll only ever compile this on Panther or greater, so 
36 // MAC_OS_X_VERSION_10_3 is guranateed to be defined.
37 #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_3
38 #import <WebKit/WebPDFRepresentation.h>
39 #endif
40 #import <WebKit/WebResourceLoadDelegate.h>
41 #import <WebKit/WebResourcePrivate.h>
42 #import <WebKit/WebTextRepresentation.h>
43 #import <WebKit/WebViewPrivate.h>
44
45 #import <Foundation/NSDictionary_NSURLExtras.h>
46 #import <Foundation/NSString_NSURLExtras.h>
47 #import <Foundation/NSURLConnection.h>
48 #import <Foundation/NSURLRequest.h>
49 #import <Foundation/NSURLResponsePrivate.h>
50
51 @implementation WebDataSourcePrivate 
52
53 - (void)dealloc
54 {
55     // The WebView is only retained while loading, but this object is also
56     // retained while loading, so no need to release here
57     ASSERT(!loading);
58
59     [resourceData release];
60     [representation release];
61     [request release];
62     [originalRequest release];
63     [originalRequestCopy release];
64     [mainClient release];
65     [subresourceClients release];
66     [plugInStreamClients release];
67     [pageTitle release];
68     [response release];
69     [mainDocumentError release];
70     [iconLoader release];
71     [iconURL release];
72     [ourBackForwardItems release];
73     [triggeringAction release];
74     [lastCheckedRequest release];
75     [responses release];
76     [webFrame release];
77     [subresources release];
78     [pendingSubframeArchives release];
79
80     [super dealloc];
81 }
82
83 @end
84
85 @implementation WebDataSource (WebPrivate)
86
87 - (void)_addSubresources:(NSArray *)subresources
88 {
89     NSEnumerator *enumerator = [subresources objectEnumerator];
90     WebResource *subresource;
91     while ((subresource = [enumerator nextObject]) != nil) {
92         [self addSubresource:subresource];
93     }
94 }
95
96 - (NSFileWrapper *)_fileWrapperForURL:(NSURL *)URL
97 {
98     if ([URL isFileURL]) {
99         NSString *path = [[URL path] stringByResolvingSymlinksInPath];
100         return [[[NSFileWrapper alloc] initWithPath:path] autorelease];
101     }
102     
103     WebResource *resource = [self subresourceForURL:URL];
104     if (resource) {
105         return [resource _fileWrapperRepresentation];
106     }
107         
108     NSCachedURLResponse *cachedResponse = [_private->webView _cachedResponseForURL:URL];
109     if (cachedResponse) {
110         NSFileWrapper *wrapper = [[[NSFileWrapper alloc] initRegularFileWithContents:[cachedResponse data]] autorelease];
111         [wrapper setPreferredFilename:[[cachedResponse response] suggestedFilename]];
112         return wrapper;
113     }
114     
115     return nil;
116 }
117
118 - (WebArchive *)_archiveWithMarkupString:(NSString *)markupString nodes:(NSArray *)nodes
119
120     WebFrame *frame = [self webFrame];
121     NSURLResponse *response = [self response];
122     WebResource *mainResource = [[WebResource alloc] initWithData:[markupString dataUsingEncoding:NSUTF8StringEncoding]
123                                                               URL:[response URL] 
124                                                          MIMEType:[response MIMEType]
125                                                  textEncodingName:@"UTF-8"
126                                                         frameName:[frame name]];
127     
128     NSMutableArray *subframeArchives = [[NSMutableArray alloc] init];
129     NSMutableArray *subresources = [[NSMutableArray alloc] init];
130     NSEnumerator *enumerator = [nodes objectEnumerator];
131     DOMNode *node;
132     while ((node = [enumerator nextObject]) != nil) {
133         WebFrame *childFrame;
134         if (([node isKindOfClass:[DOMHTMLFrameElement class]] || 
135              [node isKindOfClass:[DOMHTMLIFrameElement class]] || 
136              [node isKindOfClass:[DOMHTMLObjectElement class]]) &&
137             ((childFrame = [(DOMHTMLFrameElement *)node contentFrame]) != nil)) {
138             [subframeArchives addObject:[[childFrame dataSource] _archiveWithCurrentState:YES]];
139         } else {
140             NSEnumerator *enumerator = [[node _subresourceURLs] objectEnumerator];
141             NSURL *URL;
142             while ((URL = [enumerator nextObject]) != nil) {
143                 WebResource *subresource = [self subresourceForURL:URL];
144                 if (subresource) {
145                     [subresources addObject:subresource];
146                 } else {
147                     ERROR("Failed to archive subresource for %@", URL);
148                 }
149             }
150         }
151     }
152     
153     WebArchive *archive = [[[WebArchive alloc] initWithMainResource:mainResource subresources:subresources subframeArchives:subframeArchives] autorelease];
154     [mainResource release];
155     [subresources release];
156     [subframeArchives release];
157     
158     return archive;
159 }
160
161 - (WebArchive *)_archiveWithCurrentState:(BOOL)currentState
162 {
163     if (currentState && [[self representation] conformsToProtocol:@protocol(WebDocumentDOM)]) {
164         return [[(id <WebDocumentDOM>)[self representation] DOMDocument] webArchive];
165     } else {
166         NSEnumerator *enumerator = [[[self webFrame] childFrames] objectEnumerator];
167         NSMutableArray *subframeArchives = [[NSMutableArray alloc] init];
168         WebFrame *childFrame;
169         while ((childFrame = [enumerator nextObject]) != nil) {
170             [subframeArchives addObject:[[childFrame dataSource] _archiveWithCurrentState:currentState]];
171         }
172         WebArchive *archive = [[[WebArchive alloc] initWithMainResource:[self mainResource] 
173                                                            subresources:[_private->subresources allValues]
174                                                        subframeArchives:subframeArchives] autorelease];
175         [subframeArchives release];
176         return archive;
177     }
178 }
179
180 - (void)_addSubframeArchives:(NSArray *)subframeArchives
181 {
182     if (_private->pendingSubframeArchives == nil) {
183         _private->pendingSubframeArchives = [[NSMutableDictionary alloc] init];
184     }
185     
186     NSEnumerator *enumerator = [subframeArchives objectEnumerator];
187     WebArchive *archive;
188     while ((archive = [enumerator nextObject]) != nil) {
189         NSString *frameName = [[archive mainResource] frameName];
190         if (frameName) {
191             [_private->pendingSubframeArchives setObject:archive forKey:frameName];
192         }
193     }
194 }
195
196 - (WebArchive *)_popSubframeArchiveWithName:(NSString *)frameName
197 {
198     ASSERT(frameName != nil);
199     
200     WebArchive *archive = [[[_private->pendingSubframeArchives objectForKey:frameName] retain] autorelease];
201     if (archive != nil) {
202         [_private->pendingSubframeArchives removeObjectForKey:frameName];
203     }
204     return archive;
205 }
206
207 - (DOMElement *)_imageElementWithImageResource:(WebResource *)resource
208 {
209     ASSERT(resource);
210     [self addSubresource:resource];
211     
212     DOMElement *imageElement = [[[self _bridge] DOMDocument] createElement:@"img"];
213     
214     // FIXME: calling _web_originalDataAsString on a file URL returns an absolute path. Workaround this.
215     NSURL *URL = [resource URL];
216     [imageElement setAttribute:@"src" :[URL isFileURL] ? [URL absoluteString] : [URL _web_originalDataAsString]];
217     
218     return imageElement;
219 }
220
221 - (DOMDocumentFragment *)_documentFragmentWithImageResource:(WebResource *)resource
222 {
223     DOMDocumentFragment *fragment = [[[self _bridge] DOMDocument] createDocumentFragment];
224     [fragment appendChild:[self _imageElementWithImageResource:resource]];
225     return fragment;
226 }
227
228 - (DOMDocumentFragment *)_documentFragmentWithArchive:(WebArchive *)archive
229 {
230     ASSERT(archive);
231     WebResource *mainResource = [archive mainResource];
232     if (mainResource) {
233         NSString *MIMEType = [mainResource MIMEType];
234         if ([WebView canShowMIMETypeAsHTML:MIMEType]) {
235             NSString *markupString = [[NSString alloc] initWithData:[mainResource data] encoding:NSUTF8StringEncoding];
236             [self _addSubresources:[archive subresources]];
237             [self _addSubframeArchives:[archive subframeArchives]];
238             DOMDocumentFragment *fragment = [[self _bridge] documentFragmentWithMarkupString:markupString baseURLString:[[mainResource URL] _web_originalDataAsString]];
239             [markupString release];
240             return fragment;
241         } else if ([[[WebImageRendererFactory sharedFactory] supportedMIMETypes] containsObject:MIMEType]) {
242             return [self _documentFragmentWithImageResource:mainResource];
243
244         }
245     }
246     return nil;
247 }
248
249 - (void)_replaceSelectionWithArchive:(WebArchive *)archive selectReplacement:(BOOL)selectReplacement
250 {
251     DOMDocumentFragment *fragment = [self _documentFragmentWithArchive:archive];
252     if (fragment) {
253         [[self _bridge] replaceSelectionWithFragment:fragment selectReplacement:selectReplacement];
254     }
255 }
256
257 - (WebView *)_webView
258 {
259     return _private->webView;
260 }
261
262 - (void)_setRepresentation: (id<WebDocumentRepresentation>)representation
263 {
264     [_private->representation release];
265     _private->representation = [representation retain];
266 }
267
268 - (void)_setLoading:(BOOL)loading
269 {
270     ASSERT_ARG(loading, loading == NO || loading == YES);
271
272     if (_private->loading == loading) {
273         return;
274     }
275     
276     _private->loading = loading;
277     
278     if (loading) {
279         [self retain];
280         [_private->webView retain];
281     } else {
282         [_private->webView release];
283         // FIXME: It would be cleanest to set webView to nil here. Keeping a non-retained reference
284         // to the WebView is dangerous. But WebSubresourceClient actually depends on this non-retained
285         // reference when starting loads after the data source has stoppped loading.
286         [self release];
287     }
288 }
289
290 - (void)_updateLoading
291 {
292     [self _setLoading:_private->mainClient || [_private->subresourceClients count]];
293 }
294
295 - (void)_setWebView: (WebView *)webView
296 {
297     if (_private->loading) {
298         [webView retain];
299         [_private->webView release];
300     }
301     _private->webView = webView;
302     
303     [self _defersCallbacksChanged];
304 }
305
306 - (void)_setPrimaryLoadComplete: (BOOL)flag
307 {
308     _private->primaryLoadComplete = flag;
309     
310     if (flag) {
311         // FIXME: We could actually load it as soon as we've parsed
312         // the HEAD section, or determined there isn't one - but
313         // there's no callback for that.
314         [self _loadIcon];
315
316         [_private->mainClient release];
317         _private->mainClient = 0; 
318         [self _updateLoading];
319     }
320 }
321
322 - (void)_startLoading
323 {
324     [self _startLoading: nil];
325 }
326
327
328 // Cancels any pending loads.  A data source is conceptually only ever loading
329 // one document at a time, although one document may have many related
330 // resources.  stopLoading will stop all loads related to the data source.  This
331 // method will also stop loads that may be loading in child frames.
332 - (void)_stopLoading
333 {
334     [self _recursiveStopLoading];
335 }
336
337
338 - (void)_startLoading: (NSDictionary *)pageCache
339 {
340     ASSERT([self _isStopping] == NO);
341
342     [self _setPrimaryLoadComplete: NO];
343     
344     ASSERT([self webFrame] != nil);
345     
346     [self _clearErrors];
347     
348     // Mark the start loading time.
349     _private->loadingStartedTime = CFAbsoluteTimeGetCurrent();
350     
351     [self _setLoading:YES];
352
353     [_private->webView _progressStarted:[self webFrame]];
354     
355     [_private->webView _didStartProvisionalLoadForFrame:[self webFrame]];
356     [[_private->webView _frameLoadDelegateForwarder] webView:_private->webView
357                                      didStartProvisionalLoadForFrame:[self webFrame]];
358
359     if (pageCache){
360         _private->loadingFromPageCache = YES;
361         [self _commitIfReady: pageCache];
362     } else if (!_private->mainClient) {
363         _private->loadingFromPageCache = NO;
364         
365         id identifier;
366         id resourceLoadDelegate = [_private->webView resourceLoadDelegate];
367         if ([resourceLoadDelegate respondsToSelector:@selector(webView:identifierForInitialRequest:fromDataSource:)])
368             identifier = [resourceLoadDelegate webView:_private->webView identifierForInitialRequest:_private->originalRequest fromDataSource:self];
369         else
370             identifier = [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:_private->webView identifierForInitialRequest:_private->originalRequest fromDataSource:self];
371             
372         _private->mainClient = [[WebMainResourceClient alloc] initWithDataSource:self];
373         [_private->mainClient setIdentifier: identifier];
374         [[self webFrame] _addExtraFieldsToRequest:_private->request alwaysFromRequest: NO];
375         if (![_private->mainClient loadWithRequest:_private->request]) {
376             ERROR("could not create WebResourceHandle for URL %@ -- should be caught by policy handler level",
377                 [_private->request URL]);
378             [_private->mainClient release];
379             _private->mainClient = nil;
380             [self _updateLoading];
381         }
382     }
383 }
384
385 - (void)_addSubresourceClient:(WebBaseResourceHandleDelegate *)client
386 {
387     if (_private->subresourceClients == nil) {
388         _private->subresourceClients = [[NSMutableArray alloc] init];
389     }
390     [_private->subresourceClients addObject:client];
391     [self _setLoading:YES];
392 }
393
394 - (void)_removeSubresourceClient:(WebBaseResourceHandleDelegate *)client
395 {
396     [_private->subresourceClients removeObject:client];
397     [self _updateLoading];
398 }
399
400 - (void)_addPlugInStreamClient:(WebBaseResourceHandleDelegate *)client
401 {
402     if (_private->plugInStreamClients == nil) {
403         _private->plugInStreamClients = [[NSMutableArray alloc] init];
404     }
405     [_private->plugInStreamClients addObject:client];
406     [self _setLoading:YES];
407 }
408
409 - (void)_removePlugInStreamClient:(WebBaseResourceHandleDelegate *)client
410 {
411     [_private->plugInStreamClients removeObject:client];
412     [self _updateLoading];
413 }
414
415 - (BOOL)_isStopping
416 {
417     return _private->stopping;
418 }
419
420 - (void)_stopLoadingInternal
421 {
422     // Always attempt to stop the icon loader because it may still be loading after the data source
423     // is done loading and not stopping it can cause a world leak.
424     [_private->iconLoader stopLoading];
425
426     if (!_private->loading) {
427         return;
428     }
429
430     _private->stopping = YES;
431
432     if(_private->mainClient){
433         // Stop the main handle and let it set the cancelled error.
434         [_private->mainClient cancel];
435     }else{
436         // Main handle is already done. Set the cancelled error.
437         NSError *cancelledError = [NSError _webKitErrorWithDomain:NSURLErrorDomain
438                                                              code:NSURLErrorCancelled
439                                                               URL:[self _URL]];
440         [self _setMainDocumentError:cancelledError];
441     }
442     
443     NSArray *clients = [_private->subresourceClients copy];
444     [clients makeObjectsPerformSelector:@selector(cancel)];
445     [clients release];
446     
447     if (_private->committed) {
448         [[self _bridge] closeURL];        
449     }
450 }
451
452 - (void)_recursiveStopLoading
453 {
454     [self retain];
455     
456     // We depend on the WebView in the webFrame method and we release it in _stopLoading,
457     // so call webFrame first so we don't send a message the released WebView (3129503).
458     [[[self webFrame] childFrames] makeObjectsPerformSelector:@selector(stopLoading)];
459     [self _stopLoadingInternal];
460     
461     [self release];
462 }
463
464 - (double)_loadingStartedTime
465 {
466     return _private->loadingStartedTime;
467 }
468
469 - (NSURL *)_URLForHistory
470 {
471     // Return the URL to be used for history and B/F list.
472     // Returns nil for WebDataProtocol URLs that aren't alternates 
473     // for unreachable URLs, because these can't be stored in history.
474     NSURL *URL = [_private->originalRequestCopy URL];
475     if ([WebDataProtocol _webIsDataProtocolURL:URL]) {
476         URL = [_private->originalRequestCopy _webDataRequestUnreachableURL];
477     }
478     
479     return [URL _webkit_canonicalize];
480 }
481
482 - (void)_setTitle:(NSString *)title
483 {
484     NSString *trimmed;
485     if (title == nil) {
486         trimmed = nil;
487     } else {
488         trimmed = [title _web_stringByTrimmingWhitespace];
489         if ([trimmed length] == 0)
490             trimmed = nil;
491     }
492     if (trimmed == nil) {
493         if (_private->pageTitle == nil)
494             return;
495     } else {
496         if ([_private->pageTitle isEqualToString:trimmed])
497             return;
498     }
499     
500     if (!trimmed || [trimmed length] == 0)
501         return;
502         
503     [_private->webView _willChangeValueForKey: _WebMainFrameTitleKey];
504     [_private->pageTitle release];
505     _private->pageTitle = [trimmed copy];
506     [_private->webView _didChangeValueForKey: _WebMainFrameTitleKey];
507     
508     // The title doesn't get communicated to the WebView until we are committed.
509     if (_private->committed) {
510         NSURL *URLForHistory = [self _URLForHistory];
511         if (URLForHistory != nil) {
512             WebHistoryItem *entry = [[WebHistory optionalSharedHistory] itemForURL:URLForHistory];
513             [entry setTitle: _private->pageTitle];
514             
515             // Must update the entries in the back-forward list too.
516             [_private->ourBackForwardItems makeObjectsPerformSelector:@selector(setTitle:) withObject:_private->pageTitle];
517             
518             [[_private->webView _frameLoadDelegateForwarder] webView:_private->webView
519                                                      didReceiveTitle:_private->pageTitle
520                                                             forFrame:[self webFrame]];
521         }
522     }
523 }
524
525 - (NSString *)_title
526 {
527     return _private->pageTitle;
528 }
529
530 - (void)_setURL:(NSURL *)URL
531 {
532     NSMutableURLRequest *newOriginalRequest = [_private->originalRequestCopy mutableCopy];
533     [_private->originalRequestCopy release];
534     [newOriginalRequest setURL:URL];
535     _private->originalRequestCopy = newOriginalRequest;
536
537     NSMutableURLRequest *newRequest = [_private->request mutableCopy];
538     [_private->request release];
539     [newRequest setURL:URL];
540     _private->request = newRequest;
541 }
542
543 - (void)__adoptRequest:(NSMutableURLRequest *)request
544 {
545     if (request != _private->request){
546         [_private->request release];
547         _private->request = [request retain];
548     }
549 }
550
551 - (void)_setRequest:(NSURLRequest *)request
552 {
553     ASSERT_ARG(request, request != _private->request);
554     
555     // Replacing an unreachable URL with alternate content looks like a server-side
556     // redirect at this point, but we can replace a committed dataSource.
557     BOOL handlingUnreachableURL = [request _webDataRequestUnreachableURL] != nil;
558     if (handlingUnreachableURL) {
559         _private->committed = NO;
560     }
561     
562     // We should never be getting a redirect callback after the data
563     // source is committed, except in the unreachable URL case. It 
564     // would be a WebFoundation bug if it sent a redirect callback after commit.
565     ASSERT(!_private->committed);
566
567     NSURLRequest *oldRequest = _private->request;
568
569     _private->request = [request mutableCopy];
570
571     // Only send webView:didReceiveServerRedirectForProvisionalLoadForFrame: if URL changed.
572     // Also, don't send it when replacing unreachable URLs with alternate content.
573     if (!handlingUnreachableURL && ![[oldRequest URL] isEqual: [request URL]]) {
574         LOG(Redirect, "Server redirect to: %@", [request URL]);
575         [[_private->webView _frameLoadDelegateForwarder] webView:_private->webView
576                       didReceiveServerRedirectForProvisionalLoadForFrame:[self webFrame]];
577     }
578         
579     [oldRequest release];
580 }
581
582 - (void)_setResponse:(NSURLResponse *)response
583 {
584     [_private->response release];
585     _private->response = [response retain];
586 }
587
588 - (void)_setOverrideEncoding:(NSString *)overrideEncoding
589 {
590     NSString *copy = [overrideEncoding copy];
591     [_private->overrideEncoding release];
592     _private->overrideEncoding = copy;
593 }
594
595 - (NSString *)_overrideEncoding
596 {
597     return [[_private->overrideEncoding copy] autorelease];
598 }
599
600 - (void)_setIsClientRedirect:(BOOL)flag
601 {
602     _private->isClientRedirect = flag;
603 }
604
605 - (BOOL)_isClientRedirect
606 {
607     return _private->isClientRedirect;
608 }
609
610 - (void)_addBackForwardItem:(WebHistoryItem *)item
611 {
612     if (!item) {
613         return;
614     }
615     if (!_private->ourBackForwardItems) {
616         _private->ourBackForwardItems = [[NSMutableArray alloc] initWithCapacity:1];
617     }
618     if ([_private->ourBackForwardItems indexOfObjectIdenticalTo:item] == NSNotFound) {
619         [_private->ourBackForwardItems addObject:item];
620     }
621 }
622
623 - (void)_addBackForwardItems:(NSArray *)items
624 {
625     if (!items || [items count] == 0) {
626         return;
627     }
628     if (!_private->ourBackForwardItems) {
629         _private->ourBackForwardItems = [items mutableCopy];
630     } else {
631         [_private->ourBackForwardItems addObjectsFromArray:items];
632     }
633 }
634
635 - (NSArray *)_backForwardItems
636 {
637     return _private->ourBackForwardItems;
638 }
639
640 - (void)_setMainDocumentError: (NSError *)error
641 {
642     [error retain];
643     [_private->mainDocumentError release];
644     _private->mainDocumentError = error;
645
646     [[self representation] receivedError:error withDataSource:self];
647 }
648
649 - (void)_clearErrors
650 {
651     [_private->mainDocumentError release];
652     _private->mainDocumentError = nil;
653 }
654
655 + (NSMutableDictionary *)_repTypesAllowImageTypeOmission:(BOOL)allowImageTypeOmission
656 {
657     static NSMutableDictionary *repTypes = nil;
658     static BOOL addedImageTypes;
659     
660     if (!repTypes) {
661         repTypes = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
662             [WebHTMLRepresentation class], @"text/html",
663             [WebHTMLRepresentation class], @"text/xml",
664             [WebHTMLRepresentation class], @"text/xsl",
665             [WebHTMLRepresentation class], @"application/xml",
666             [WebHTMLRepresentation class], @"application/xhtml+xml",
667             [WebHTMLRepresentation class], @"application/x-webarchive",
668             [WebTextRepresentation class], @"text/",
669             [WebTextRepresentation class], @"application/x-javascript",
670 // Assume we'll only ever compile this on Panther or greater, so 
671 // MAC_OS_X_VERSION_10_3 is guranateed to be defined.
672 #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_3
673             [WebPDFRepresentation class], @"application/pdf",
674 #endif
675             nil];
676     }
677     
678     if (!addedImageTypes && !allowImageTypeOmission) {
679         NSEnumerator *enumerator = [[WebImageView supportedImageMIMETypes] objectEnumerator];
680         NSString *mime;
681         while ((mime = [enumerator nextObject]) != nil) {
682             // Don't clobber previously-registered rep classes.
683             if ([repTypes objectForKey:mime] == nil) {
684                 [repTypes setObject:[WebImageRepresentation class] forKey:mime];
685             }
686         }
687         addedImageTypes = YES;
688     }
689     
690     return repTypes;
691 }
692
693 + (Class)_representationClassForMIMEType:(NSString *)MIMEType
694 {
695     Class repClass;
696     return [WebView _viewClass:nil andRepresentationClass:&repClass forMIMEType:MIMEType] ? repClass : nil;
697 }
698
699 - (WebBridge *)_bridge
700 {
701     ASSERT(_private->committed);
702     return [[self webFrame] _bridge];
703 }
704
705 - (BOOL)_isCommitted
706 {
707     return _private->committed;
708 }
709
710 - (void)_commitIfReady: (NSDictionary *)pageCache
711 {
712     if (_private->loadingFromPageCache || (_private->gotFirstByte && !_private->committed)) {
713         WebFrame *frame = [self webFrame];
714         WebFrameLoadType loadType = [frame _loadType];
715         bool reload = loadType == WebFrameLoadTypeReload
716             || loadType == WebFrameLoadTypeReloadAllowingStaleData;
717         
718         NSDictionary *headers = [_private->response isKindOfClass:[NSHTTPURLResponse class]]
719             ? [(NSHTTPURLResponse *)_private->response allHeaderFields] : nil;
720
721         [frame _closeOldDataSources];
722
723         LOG(Loading, "committed resource = %@", [[self request] URL]);
724         _private->committed = TRUE;
725         if (!pageCache)
726             [self _makeRepresentation];
727             
728         [frame _transitionToCommitted: pageCache];
729
730         NSURL *baseURL = [[self request] _webDataRequestBaseURL];        
731         NSURL *URL = nil;
732         
733         if (baseURL)
734             URL = baseURL;
735         else
736             URL = [_private->response URL];
737             
738         // WebCore will crash if given an empty URL here.
739         // FIXME: could use CFURL, when available, range API to save an allocation here
740         if (!URL || [URL _web_isEmpty])
741             URL = [NSURL URLWithString:@"about:blank"];
742
743         [[self _bridge] openURL:URL
744                          reload:reload 
745                     contentType:[_private->response MIMEType]
746                         refresh:[headers objectForKey:@"Refresh"]
747                    lastModified:(pageCache ? nil : [_private->response _lastModifiedDate])
748                       pageCache:pageCache];
749
750         [frame _opened];
751     }
752 }
753
754 - (void)_commitIfReady
755 {
756     [self _commitIfReady: nil];
757 }
758
759 -(void)_makeRepresentation
760 {
761     Class repClass = [[self class] _representationClassForMIMEType:[[self response] MIMEType]];
762     
763     // Check if the data source was already bound?
764     if (![[self representation] isKindOfClass:repClass]) {
765         id newRep = repClass != nil ? [[repClass alloc] init] : nil;
766         [self _setRepresentation:(id <WebDocumentRepresentation>)newRep];
767         [newRep release];
768     }
769
770     [_private->representation setDataSource:self];
771 }
772
773 -(void)_receivedData:(NSData *)data
774 {
775     if (!_private->resourceData) {
776         _private->resourceData = [[NSMutableData alloc] init];
777     }
778     ASSERT([_private->resourceData isKindOfClass:[NSMutableData class]]);
779     [_private->resourceData appendData:data];
780     
781     _private->gotFirstByte = YES;
782     [self _commitIfReady];
783
784     // parsing some of the page can result in running a script which
785     // could possibly destroy the frame and data source. So retain
786     // self temporarily.
787     [self retain];
788     [[self representation] receivedData:data withDataSource:self];
789     [[[[self webFrame] frameView] documentView] dataSourceUpdated:self];
790     [self release];
791 }
792
793 - (void)_setData:(NSData *)data
794 {
795     [data retain];
796     [_private->resourceData release];
797     _private->resourceData = (NSMutableData *)data;
798 }
799
800 - (void)_finishedLoading
801 {
802     _private->gotFirstByte = YES;
803     [self _commitIfReady];
804
805     [[self representation] finishedLoadingWithDataSource:self];
806     // Since we've sent openURL to the bridge, it's important to send end too, so that WebCore
807     // can realize that the load is completed.
808     [[self _bridge] end];
809 }
810
811 - (void)_receivedMainResourceError:(NSError *)error complete:(BOOL)isComplete
812 {
813     if (isComplete) {
814         // Can't call [self _bridge] because we might not have commited yet
815         [[[self webFrame] _bridge] end];
816     }        
817     [[self webFrame] _receivedMainResourceError:error];
818     [[self _webView] _mainReceivedError:error
819                            fromDataSource:self
820                                  complete:isComplete];
821 }
822
823 - (void)_updateIconDatabaseWithURL:(NSURL *)iconURL
824 {
825     WebIconDatabase *iconDB = [WebIconDatabase sharedIconDatabase];
826
827     // Bind the URL of the original request and the final URL to the icon URL.
828     [iconDB _setIconURL:[iconURL _web_originalDataAsString] forURL:[[self _URL] _web_originalDataAsString]];
829     [iconDB _setIconURL:[iconURL _web_originalDataAsString] forURL:[[[self _originalRequest] URL] _web_originalDataAsString]];
830
831     
832     if ([self webFrame] == [_private->webView mainFrame])
833         [_private->webView _willChangeValueForKey:_WebMainFrameIconKey];
834     
835     NSImage *icon = [iconDB iconForURL:[[self _URL] _web_originalDataAsString] withSize:WebIconSmallSize];
836     [[_private->webView _frameLoadDelegateForwarder] webView:_private->webView
837                                                       didReceiveIcon:icon
838                                                             forFrame:[self webFrame]];
839     
840     if ([self webFrame] == [_private->webView mainFrame])
841         [_private->webView _didChangeValueForKey:_WebMainFrameIconKey];
842 }
843
844 - (void)_iconLoaderReceivedPageIcon:(WebIconLoader *)iconLoader
845 {
846     [self _updateIconDatabaseWithURL:[iconLoader URL]];
847 }
848
849 - (void)_loadIcon
850 {
851     // 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.
852     if ([self webFrame] != [[self _webView] mainFrame] || _private->mainDocumentError || _private->iconLoader ||
853        ![[WebIconDatabase sharedIconDatabase] iconsAreSaved]) {
854         return;
855     }
856                 
857     if(!_private->iconURL){
858         // No icon URL from the LINK tag so try the server's root.
859         // This is only really a feature of http or https, so don't try this with other protocols.
860         NSString *scheme = [[self _URL] scheme];
861         if([scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"]){
862             _private->iconURL = [[[NSURL _web_URLWithDataAsString:@"/favicon.ico"
863                                               relativeToURL:[self _URL]] absoluteURL] retain];
864         }
865     }
866
867     if(_private->iconURL != nil){
868         if([[WebIconDatabase sharedIconDatabase] _hasIconForIconURL:[_private->iconURL _web_originalDataAsString]]){
869             [self _updateIconDatabaseWithURL:_private->iconURL];
870         }else{
871             ASSERT(!_private->iconLoader);
872             NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:_private->iconURL];
873             [[self webFrame] _addExtraFieldsToRequest:request alwaysFromRequest:NO];
874             _private->iconLoader = [[WebIconLoader alloc] initWithRequest:request];
875             [request release];
876             [_private->iconLoader setDelegate:self];
877             [_private->iconLoader setDataSource:self];
878             [_private->iconLoader startLoading];
879         }
880     }
881 }
882
883 - (void)_setIconURL:(NSURL *)URL
884 {
885     // Lower priority than typed icon, so ignore this if we already have an iconURL.
886     if (_private->iconURL == nil) {
887         [_private->iconURL release];
888         _private->iconURL = [URL retain];
889     }
890 }
891
892 - (void)_setIconURL:(NSURL *)URL withType:(NSString *)iconType
893 {
894     // FIXME: Should check to make sure the type is one we know how to handle.
895     [_private->iconURL release];
896     _private->iconURL = [URL retain];
897 }
898
899 - (void)_defersCallbacksChanged
900 {
901     BOOL defers = [_private->webView defersCallbacks];
902     
903     if (defers == _private->defersCallbacks) {
904         return;
905     }
906
907     _private->defersCallbacks = defers;
908     [_private->mainClient setDefersCallbacks:defers];
909
910     NSEnumerator *e = [_private->subresourceClients objectEnumerator];
911     WebBaseResourceHandleDelegate *client;
912     while ((client = [e nextObject])) {
913         [client setDefersCallbacks:defers];
914     }
915     e = [_private->plugInStreamClients objectEnumerator];
916     while ((client = [e nextObject])) {
917         [client setDefersCallbacks:defers];
918     }
919
920     // It's OK to use the internal version of getting the child
921     // frames, since undeferring callbacks will not do any immediate
922     // work, and so the set of frames can't change out from under us.
923     [[[self webFrame] _internalChildFrames] makeObjectsPerformSelector:@selector(_defersCallbacksChanged)];
924 }
925
926 - (NSURLRequest *)_originalRequest
927 {
928     return _private->originalRequestCopy;
929 }
930
931 - (void)_setTriggeringAction:(NSDictionary *)action
932 {
933     [action retain];
934     [_private->triggeringAction release];
935     _private->triggeringAction = action;
936 }
937
938 - (NSDictionary *)_triggeringAction
939 {
940     return [[_private->triggeringAction retain] autorelease];
941 }
942
943
944 - (NSURLRequest *)_lastCheckedRequest
945 {
946     // It's OK not to make a copy here because we know the caller
947     // isn't going to modify this request
948     return [[_private->lastCheckedRequest retain] autorelease];
949 }
950
951 - (void)_setLastCheckedRequest:(NSURLRequest *)request
952 {
953     NSURLRequest *oldRequest = _private->lastCheckedRequest;
954     _private->lastCheckedRequest = [request copy];
955     [oldRequest release];
956 }
957
958 - (void)_setJustOpenedForTargetedLink:(BOOL)justOpened
959 {
960     _private->justOpenedForTargetedLink = justOpened;
961 }
962
963 - (BOOL)_justOpenedForTargetedLink
964 {
965     return _private->justOpenedForTargetedLink;
966 }
967
968 - (void)_setStoredInPageCache:(BOOL)f
969 {
970     _private->storedInPageCache = f;
971 }
972
973 - (BOOL)_storedInPageCache
974 {
975     return _private->storedInPageCache;
976 }
977
978 - (BOOL)_loadingFromPageCache
979 {
980     return _private->loadingFromPageCache;
981 }
982
983 - (void)_addResponse: (NSURLResponse *)r
984 {
985     if (!_private->responses)
986         _private->responses = [[NSMutableArray alloc] init];
987     [_private->responses addObject: r];
988 }
989
990 - (NSArray *)_responses
991 {
992     return _private->responses;
993 }
994
995 - (void)_stopLoadingWithError:(NSError *)error
996 {
997     [_private->mainClient cancelWithError:error];
998 }
999
1000 - (void)_setWebFrame:(WebFrame *)frame
1001 {
1002     [frame retain];
1003     [_private->webFrame release];
1004     _private->webFrame = frame;
1005 }
1006
1007 // May return nil if not initialized with a URL.
1008 - (NSURL *)_URL
1009 {
1010     return [[self request] URL];
1011 }
1012
1013 - (NSString *)_stringWithData:(NSData *)data
1014 {
1015     NSString *textEncodingName = [self textEncodingName];
1016
1017     if (textEncodingName) {
1018         return [WebBridge stringWithData:data textEncodingName:textEncodingName];
1019     } else {
1020         return [WebBridge stringWithData:data textEncoding:kCFStringEncodingISOLatin1];
1021     }
1022 }
1023
1024 - (NSError *)_mainDocumentError
1025 {
1026     return _private->mainDocumentError;
1027 }
1028
1029 - (BOOL)_isDocumentHTML
1030 {
1031     NSString *MIMEType = [[self response] MIMEType];
1032     return [WebView canShowMIMETypeAsHTML:MIMEType];
1033 }
1034
1035 @end
1036
1037 @implementation WebDataSource
1038
1039 -(id)initWithRequest:(NSURLRequest *)request
1040 {
1041     self = [super init];
1042     if (!self) {
1043         return nil;
1044     }
1045     
1046     _private = [[WebDataSourcePrivate alloc] init];
1047     _private->originalRequest = [request retain];
1048     _private->originalRequestCopy = [request copy];
1049     
1050     _private->subresources = [[NSMutableDictionary alloc] init];
1051     
1052     LOG(Loading, "creating datasource for %@", [request URL]);
1053     _private->request = [_private->originalRequest mutableCopy];
1054
1055     ++WebDataSourceCount;
1056     
1057     return self;
1058 }
1059
1060 - (void)dealloc
1061 {
1062     --WebDataSourceCount;
1063     
1064     [_private->iconLoader setDelegate:nil];
1065     [_private release];
1066     
1067     [super dealloc];
1068 }
1069
1070 - (void)finalize
1071 {
1072     --WebDataSourceCount;
1073
1074     [_private->iconLoader setDelegate:nil];
1075
1076     [super finalize];
1077 }
1078
1079 - (NSData *)data
1080 {
1081     return _private->resourceData;
1082 }
1083
1084 - (id <WebDocumentRepresentation>) representation
1085 {
1086     return _private->representation;
1087 }
1088
1089 - (WebFrame *)webFrame
1090 {
1091     return _private->webFrame;
1092 }
1093
1094 -(NSURLRequest *)initialRequest
1095 {
1096     NSURLRequest *clientRequest = [_private->originalRequest _webDataRequestExternalRequest];
1097     if (!clientRequest)
1098         clientRequest = _private->originalRequest;
1099     return clientRequest;
1100 }
1101
1102 -(NSMutableURLRequest *)request
1103 {
1104     NSMutableURLRequest *clientRequest = [_private->request _webDataRequestExternalRequest];
1105     if (!clientRequest)
1106         clientRequest = _private->request;
1107     return clientRequest;
1108 }
1109
1110 - (NSURLResponse *)response
1111 {
1112     return _private->response;
1113 }
1114
1115 - (NSString *)textEncodingName
1116 {
1117     NSString *textEncodingName = [self _overrideEncoding];
1118
1119     if (!textEncodingName) {
1120         textEncodingName = [[self response] textEncodingName];
1121     }
1122     return textEncodingName;
1123 }
1124
1125 // Returns YES if there are any pending loads.
1126 - (BOOL)isLoading
1127 {
1128     // Once a frame has loaded, we no longer need to consider subresources,
1129     // but we still need to consider subframes.
1130     if ([[self webFrame] _state] != WebFrameStateComplete) {
1131         if (!_private->primaryLoadComplete && _private->loading) {
1132             return YES;
1133         }
1134         if ([_private->subresourceClients count]) {
1135             return YES;
1136         }
1137     }
1138     
1139     // Put in the auto-release pool because it's common to call this from a run loop source,
1140     // and then the entire list of frames lasts until the next autorelease.
1141     NSAutoreleasePool *pool = [NSAutoreleasePool new];
1142
1143     // It's OK to use the internal version of getting the child
1144     // frames, since nothing we do here can possibly change the set of
1145     // frames.
1146     NSEnumerator *e = [[[self webFrame] _internalChildFrames] objectEnumerator];
1147     WebFrame *childFrame;
1148     while ((childFrame = [e nextObject])) {
1149         if ([[childFrame dataSource] isLoading] || [[childFrame provisionalDataSource] isLoading]) {
1150             break;
1151         }
1152     }
1153
1154 #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_3
1155     [pool release];
1156 #else
1157     [pool drain];
1158 #endif
1159     
1160     return childFrame != nil;
1161 }
1162
1163
1164 // Returns nil or the page title.
1165 - (NSString *)pageTitle
1166 {
1167     return [[self representation] title];
1168 }
1169
1170 - (NSURL *)unreachableURL
1171 {
1172     return [_private->originalRequest _webDataRequestUnreachableURL];
1173 }
1174
1175 - (WebArchive *)webArchive
1176 {
1177     return [self _archiveWithCurrentState:NO];
1178 }
1179
1180 - (WebResource *)mainResource
1181 {
1182     NSURLResponse *response = [self response];
1183     return [[[WebResource alloc] initWithData:[self data]
1184                                           URL:[response URL] 
1185                                      MIMEType:[response MIMEType]
1186                              textEncodingName:[response textEncodingName]
1187                                     frameName:[[self webFrame] name]] autorelease];
1188 }
1189
1190 - (NSArray *)subresources
1191 {
1192     return [_private->subresources allValues];
1193 }
1194
1195 - (WebResource *)subresourceForURL:(NSURL *)URL
1196 {
1197     return [_private->subresources objectForKey:[URL _web_originalDataAsString]];
1198 }
1199
1200 - (void)addSubresource:(WebResource *)subresource
1201 {
1202     [_private->subresources setObject:subresource forKey:[[subresource URL] _web_originalDataAsString]];
1203 }
1204
1205 @end