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