Reviewed by Alice.
[WebKit-https.git] / WebKit / Loader / WebFrameLoader.m
1 /*
2  * Copyright (C) 2006 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 <WebKit/WebFrameLoader.h>
30
31 #import <JavaScriptCore/Assertions.h>
32 #import <WebKit/WebDataSourceInternal.h>
33 #import <WebKit/WebFrameInternal.h>
34 #import <WebKit/WebMainResourceLoader.h>
35 #import <WebKit/WebKitLogging.h>
36 #import <WebKit/WebViewInternal.h>
37 #import <WebKit/WebKitErrorsPrivate.h>
38 #import <WebKit/WebResourcePrivate.h>
39 #import <WebKit/DOMHTML.h>
40 #import <WebKit/WebFrameBridge.h>
41 #import <WebKit/WebPreferences.h>
42 #import <WebKit/WebIconDatabasePrivate.h>
43 #import <WebKit/WebNSURLExtras.h>
44 #import <WebKit/WebFrameLoadDelegate.h>
45 #import <WebKit/WebDataProtocol.h>
46 #import <WebKit/WebKitNSStringExtras.h>
47 #import "WebNSDictionaryExtras.h"
48
49 @implementation WebFrameLoader
50
51 - (id)initWithWebFrame:(WebFrame *)wf
52 {
53     self = [super init];
54     if (self) {
55         webFrame = wf;
56         state = WebFrameStateCommittedPage;
57     }
58     return self;    
59 }
60
61 - (void)dealloc
62 {
63     // FIXME: should these even exist?
64     [mainResourceLoader release];
65     [subresourceLoaders release];
66     [plugInStreamLoaders release];
67     [documentLoadState release];
68     [provisionalDocumentLoadState release];
69  
70     ASSERT(!policyDocumentLoadState);
71     
72     [super dealloc];
73 }
74
75 - (WebDocumentLoadState *)activeDocumentLoadState
76 {
77     if (state == WebFrameStateProvisional)
78         return provisionalDocumentLoadState;
79     
80     return documentLoadState;    
81 }
82
83 - (WebDataSource *)activeDataSource
84 {
85     return [webFrame _dataSourceForDocumentLoadState:[self activeDocumentLoadState]];
86 }
87
88 - (WebResource *)_archivedSubresourceForURL:(NSURL *)URL
89 {
90     return [[self activeDataSource] _archivedSubresourceForURL:URL];
91 }
92
93 - (void)addPlugInStreamLoader:(WebLoader *)loader
94 {
95     if (!plugInStreamLoaders)
96         plugInStreamLoaders = [[NSMutableArray alloc] init];
97     [plugInStreamLoaders addObject:loader];
98     [[self activeDocumentLoadState] setLoading:YES];
99 }
100
101 - (void)removePlugInStreamLoader:(WebLoader *)loader
102 {
103     [plugInStreamLoaders removeObject:loader];
104     [[self activeDocumentLoadState] updateLoading];
105 }    
106
107 - (void)defersCallbacksChanged
108 {
109     [self setDefersCallbacks:[[webFrame webView] defersCallbacks]];
110 }
111
112 - (BOOL)defersCallbacks
113 {
114     return [[webFrame webView] defersCallbacks];
115 }
116
117 - (void)setDefersCallbacks:(BOOL)defers
118 {
119     [mainResourceLoader setDefersCallbacks:defers];
120     
121     NSEnumerator *e = [subresourceLoaders objectEnumerator];
122     WebLoader *loader;
123     while ((loader = [e nextObject]))
124         [loader setDefersCallbacks:defers];
125     
126     e = [plugInStreamLoaders objectEnumerator];
127     while ((loader = [e nextObject]))
128         [loader setDefersCallbacks:defers];
129
130     [self deliverArchivedResourcesAfterDelay];
131 }
132
133 - (void)stopLoadingPlugIns
134 {
135     [plugInStreamLoaders makeObjectsPerformSelector:@selector(cancel)];
136     [plugInStreamLoaders removeAllObjects];   
137 }
138
139 - (BOOL)isLoadingMainResource
140 {
141     return mainResourceLoader != nil;
142 }
143
144 - (BOOL)isLoadingSubresources
145 {
146     return [subresourceLoaders count];
147 }
148
149 - (BOOL)isLoadingPlugIns
150 {
151     return [plugInStreamLoaders count];
152 }
153
154 - (BOOL)isLoading
155 {
156     return [self isLoadingMainResource] || [self isLoadingSubresources] || [self isLoadingPlugIns];
157 }
158
159 - (void)stopLoadingSubresources
160 {
161     NSArray *loaders = [subresourceLoaders copy];
162     [loaders makeObjectsPerformSelector:@selector(cancel)];
163     [loaders release];
164     [subresourceLoaders removeAllObjects];
165 }
166
167 - (void)addSubresourceLoader:(WebLoader *)loader
168 {
169     ASSERT(!provisionalDocumentLoadState);
170     if (subresourceLoaders == nil)
171         subresourceLoaders = [[NSMutableArray alloc] init];
172     [subresourceLoaders addObject:loader];
173     [[self activeDocumentLoadState] setLoading:YES];
174 }
175
176 - (void)removeSubresourceLoader:(WebLoader *)loader
177 {
178     [subresourceLoaders removeObject:loader];
179     [[self activeDocumentLoadState] updateLoading];
180 }
181
182 - (NSData *)mainResourceData
183 {
184     return [mainResourceLoader resourceData];
185 }
186
187 - (void)releaseMainResourceLoader
188 {
189     [mainResourceLoader release];
190     mainResourceLoader = nil;
191 }
192
193 - (void)cancelMainResourceLoad
194 {
195     [mainResourceLoader cancel];
196 }
197
198 - (BOOL)startLoadingMainResourceWithRequest:(NSMutableURLRequest *)request identifier:(id)identifier
199 {
200     mainResourceLoader = [[WebMainResourceLoader alloc] initWithFrameLoader:self];
201     
202     [mainResourceLoader setIdentifier:identifier];
203     [webFrame _addExtraFieldsToRequest:request mainResource:YES alwaysFromRequest:NO];
204     if (![mainResourceLoader loadWithRequest:request]) {
205         // FIXME: if this should really be caught, we should just ASSERT this doesn't happen;
206         // should it be caught by other parts of WebKit or other parts of the app?
207         LOG_ERROR("could not create WebResourceHandle for URL %@ -- should be caught by policy handler level", [request URL]);
208         [mainResourceLoader release];
209         mainResourceLoader = nil;
210         return NO;
211     }
212     
213     return YES;
214 }
215
216 - (void)stopLoadingWithError:(NSError *)error
217 {
218     [mainResourceLoader cancelWithError:error];
219 }
220
221 - (WebDataSource *)dataSource
222 {
223     return [webFrame _dataSourceForDocumentLoadState:documentLoadState]; 
224 }
225
226 - (void)_setDocumentLoadState:(WebDocumentLoadState *)loadState
227 {
228     if (loadState == nil && documentLoadState == nil)
229         return;
230     
231     ASSERT(loadState != documentLoadState);
232     
233     [webFrame _prepareForDataSourceReplacement];
234     [documentLoadState detachFromFrameLoader];
235     
236     [loadState retain];
237     [documentLoadState release];
238     documentLoadState = loadState;
239 }
240
241 - (WebDocumentLoadState *)documentLoadState
242 {
243     return documentLoadState;
244 }
245
246 - (WebDataSource *)policyDataSource
247 {
248     return [webFrame _dataSourceForDocumentLoadState:policyDocumentLoadState];     
249 }
250
251 - (void)_setPolicyDocumentLoadState:(WebDocumentLoadState *)loadState
252 {
253     [loadState retain];
254     [policyDocumentLoadState release];
255     policyDocumentLoadState = loadState;
256 }
257    
258 - (void)clearDataSource
259 {
260     [self _setDocumentLoadState:nil];
261 }
262
263 - (WebDataSource *)provisionalDataSource 
264 {
265     return [webFrame _dataSourceForDocumentLoadState:provisionalDocumentLoadState]; 
266 }
267
268 - (WebDocumentLoadState *)provisionalDocumentLoadState
269 {
270     return provisionalDocumentLoadState;
271 }
272
273 - (void)_setProvisionalDocumentLoadState:(WebDocumentLoadState *)loadState
274 {
275     ASSERT(!loadState || !provisionalDocumentLoadState);
276
277     if (provisionalDocumentLoadState != documentLoadState)
278         [provisionalDocumentLoadState detachFromFrameLoader];
279
280     [loadState retain];
281     [provisionalDocumentLoadState release];
282     provisionalDocumentLoadState = loadState;
283 }
284
285 - (void)_clearProvisionalDataSource
286 {
287     [self _setProvisionalDocumentLoadState:nil];
288 }
289
290 - (WebFrameState)state
291 {
292     return state;
293 }
294
295 #ifndef NDEBUG
296 static const char * const stateNames[] = {
297     "WebFrameStateProvisional",
298     "WebFrameStateCommittedPage",
299     "WebFrameStateComplete"
300 };
301 #endif
302
303 static CFAbsoluteTime _timeOfLastCompletedLoad;
304
305 + (CFAbsoluteTime)timeOfLastCompletedLoad
306 {
307     return _timeOfLastCompletedLoad;
308 }
309
310 - (void)_setState:(WebFrameState)newState
311 {
312     LOG(Loading, "%@:  transition from %s to %s", [webFrame name], stateNames[state], stateNames[newState]);
313     if ([webFrame webView])
314         LOG(Timing, "%@:  transition from %s to %s, %f seconds since start of document load", [webFrame name], stateNames[state], stateNames[newState], CFAbsoluteTimeGetCurrent() - [[[[webFrame webView] mainFrame] dataSource] _loadingStartedTime]);
315     
316     if (newState == WebFrameStateComplete && webFrame == [[webFrame webView] mainFrame])
317         LOG(DocumentLoad, "completed %@ (%f seconds)", [[[self dataSource] request] URL], CFAbsoluteTimeGetCurrent() - [[self dataSource] _loadingStartedTime]);
318     
319     state = newState;
320     
321     if (state == WebFrameStateProvisional)
322         [webFrame _provisionalLoadStarted];
323     else if (state == WebFrameStateComplete) {
324         [webFrame _frameLoadCompleted];
325         _timeOfLastCompletedLoad = CFAbsoluteTimeGetCurrent();
326         [[self dataSource] _stopRecordingResponses];
327     }
328 }
329
330 - (void)clearProvisionalLoad
331 {
332     [self _setProvisionalDocumentLoadState:nil];
333     [[webFrame webView] _progressCompleted:webFrame];
334     [self _setState:WebFrameStateComplete];
335 }
336
337 - (void)markLoadComplete
338 {
339     [self _setState:WebFrameStateComplete];
340 }
341
342 - (void)commitProvisionalLoad
343 {
344     [self stopLoadingSubresources];
345     [self stopLoadingPlugIns];
346
347     [self _setDocumentLoadState:provisionalDocumentLoadState];
348     [self _setProvisionalDocumentLoadState:nil];
349     [self _setState:WebFrameStateCommittedPage];
350 }
351
352 - (void)stopLoading
353 {
354     [[self provisionalDocumentLoadState] stopLoading];
355     [[self documentLoadState] stopLoading];
356     [self _clearProvisionalDataSource];
357     [self clearArchivedResources];
358 }
359
360 // FIXME: poor method name; also why is this not part of startProvisionalLoad:?
361 - (void)startLoading
362 {
363     [[self provisionalDataSource] _startLoading];
364 }
365
366 - (void)startProvisionalLoad:(WebDataSource *)ds
367 {
368     [self _setProvisionalDocumentLoadState:[ds _documentLoadState]];
369     [self _setState:WebFrameStateProvisional];
370 }
371
372 - (void)setupForReplace
373 {
374     [self _setState:WebFrameStateProvisional];
375     WebDocumentLoadState *old = provisionalDocumentLoadState;
376     provisionalDocumentLoadState = documentLoadState;
377     documentLoadState = nil;
378     [old release];
379     
380     [webFrame _detachChildren];
381 }
382
383 - (id)_identifierForInitialRequest:(NSURLRequest *)clientRequest
384 {
385     return [[self activeDataSource] _identifierForInitialRequest:clientRequest];
386 }
387
388 - (NSURLRequest *)_willSendRequest:(NSMutableURLRequest *)clientRequest forResource:(id)identifier redirectResponse:(NSURLResponse *)redirectResponse
389 {
390     return [[self activeDataSource] _willSendRequest:clientRequest forResource:identifier redirectResponse:redirectResponse];
391 }
392
393 - (void)_didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)currentWebChallenge forResource:(id)identifier
394 {
395     [[self activeDataSource] _didReceiveAuthenticationChallenge:currentWebChallenge forResource:identifier];
396 }
397
398 - (void)_didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)currentWebChallenge forResource:(id)identifier
399 {
400     [[self activeDataSource] _didCancelAuthenticationChallenge:currentWebChallenge forResource:identifier];
401 }
402
403 - (void)_didReceiveResponse:(NSURLResponse *)r forResource:(id)identifier
404 {
405     [[self activeDataSource] _didReceiveResponse:r forResource:identifier];
406 }
407
408 - (void)_didReceiveData:(NSData *)data contentLength:(int)lengthReceived forResource:(id)identifier
409 {
410     [[self activeDataSource] _didReceiveData:data contentLength:lengthReceived forResource:identifier];
411 }
412
413 - (void)_didFinishLoadingForResource:(id)identifier
414 {
415     [[self activeDataSource] _didFinishLoadingForResource:identifier];
416 }
417
418 - (void)_didFailLoadingWithError:(NSError *)error forResource:(id)identifier
419 {
420     [[self activeDataSource] _didFailLoadingWithError:error forResource:identifier];
421 }
422
423 - (BOOL)_privateBrowsingEnabled
424 {
425     return [[[webFrame webView] preferences] privateBrowsingEnabled];
426 }
427
428 - (void)_finishedLoadingResource
429 {
430     [webFrame _checkLoadComplete];
431 }
432
433 - (void)_receivedError:(NSError *)error
434 {
435     [webFrame _checkLoadComplete];
436 }
437
438 - (NSURLRequest *)_originalRequest
439 {
440     return [[self activeDocumentLoadState] originalRequestCopy];
441 }
442
443 - (WebFrame *)webFrame
444 {
445     return webFrame;
446 }
447
448 - (void)_receivedMainResourceError:(NSError *)error complete:(BOOL)isComplete
449 {
450     WebDataSource *ds = [self activeDataSource];
451     [ds retain];
452     [ds _receivedMainResourceError:error complete:isComplete];
453     [ds release];
454 }
455
456 - (NSURLRequest *)initialRequest
457 {
458     return [[self activeDataSource] initialRequest];
459 }
460
461 - (void)_receivedData:(NSData *)data
462 {
463     [[self activeDocumentLoadState] receivedData:data];
464 }
465
466 - (void)_setRequest:(NSURLRequest *)request
467 {
468     [[self activeDocumentLoadState] setRequest:request];
469 }
470
471 - (void)_downloadWithLoadingConnection:(NSURLConnection *)connection request:(NSURLRequest *)request response:(NSURLResponse *)r proxy:(id)proxy
472 {
473     [[self activeDataSource] _downloadWithLoadingConnection:connection request:request response:r proxy:proxy];
474 }
475
476 - (WebFrameBridge *)bridge
477 {
478     return [webFrame _bridge];
479 }
480
481 - (void)_handleFallbackContent
482 {
483     [[self bridge] handleFallbackContent];
484 }
485
486 - (BOOL)_isStopping
487 {
488     return [[self activeDocumentLoadState] isStopping];
489 }
490
491 - (void)_setupForReplaceByMIMEType:(NSString *)newMIMEType
492 {
493     [[self activeDocumentLoadState] setupForReplaceByMIMEType:newMIMEType];
494 }
495
496 - (void)_setResponse:(NSURLResponse *)response
497 {
498     [[self activeDocumentLoadState] setResponse:response];
499 }
500
501 - (void)_mainReceivedError:(NSError *)error complete:(BOOL)isComplete
502 {
503     [[self activeDocumentLoadState] mainReceivedError:error complete:isComplete];
504 }
505
506 - (void)_finishedLoading
507 {
508     WebDataSource *ds = [self activeDataSource];
509     
510     [self retain];
511     [[self activeDocumentLoadState] finishedLoading];
512
513     if ([ds _mainDocumentError] || ![ds webFrame]) {
514         [self release];
515         return;
516     }
517
518     [ds _setPrimaryLoadComplete:YES];
519     [webFrame _checkLoadComplete];
520
521     [self release];
522 }
523
524 - (void)_notifyIconChanged:(NSURL *)iconURL
525 {
526     ASSERT([[WebIconDatabase sharedIconDatabase] _isEnabled]);
527     ASSERT(webFrame == [[webFrame webView] mainFrame]);
528
529     [[webFrame webView] _willChangeValueForKey:_WebMainFrameIconKey];
530     
531     NSImage *icon = [[WebIconDatabase sharedIconDatabase] iconForURL:[[[self activeDataSource] _URL] _web_originalDataAsString] withSize:WebIconSmallSize];
532     
533     [[[webFrame webView] _frameLoadDelegateForwarder] webView:[webFrame webView]
534                                                didReceiveIcon:icon
535                                                      forFrame:webFrame];
536     
537     [[webFrame webView] _didChangeValueForKey:_WebMainFrameIconKey];
538 }
539
540 - (NSURL *)_URL
541 {
542     return [[self activeDataSource] _URL];
543 }
544
545 - (NSError *)cancelledErrorWithRequest:(NSURLRequest *)request
546 {
547     return [NSError _webKitErrorWithDomain:NSURLErrorDomain
548                                       code:NSURLErrorCancelled
549                                        URL:[request URL]];
550 }
551
552 - (NSError *)fileDoesNotExistErrorWithResponse:(NSURLResponse *)response
553 {
554     return [NSError _webKitErrorWithDomain:NSURLErrorDomain
555                                                 code:NSURLErrorFileDoesNotExist
556                                                  URL:[response URL]];    
557 }
558
559 - (void)clearArchivedResources
560 {
561     [pendingArchivedResources removeAllObjects];
562     [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(deliverArchivedResources) object:nil];
563 }
564
565 - (void)deliverArchivedResources
566 {
567     if (![pendingArchivedResources count] || [self defersCallbacks])
568         return;
569         
570     NSEnumerator *keyEnum = [pendingArchivedResources keyEnumerator];
571     WebLoader *loader;
572     while ((loader = [keyEnum nextObject])) {
573         WebResource *resource = [pendingArchivedResources objectForKey:loader];
574         [loader didReceiveResponse:[resource _response]];
575         NSData *data = [resource data];
576         [loader didReceiveData:data lengthReceived:[data length] allAtOnce:YES];
577         [loader didFinishLoading];
578     }
579     
580     [pendingArchivedResources removeAllObjects];
581 }
582
583 - (void)deliverArchivedResourcesAfterDelay
584 {
585     if (![pendingArchivedResources count] || [self defersCallbacks])
586         return;
587     
588     [self performSelector:@selector(deliverArchivedResources) withObject:nil afterDelay:0];
589 }
590
591 static BOOL isCaseInsensitiveEqual(NSString *a, NSString *b)
592 {
593     return [a caseInsensitiveCompare:b] == NSOrderedSame;
594 }
595
596 // The following 2 methods are copied from [NSHTTPURLProtocol _cachedResponsePassesValidityChecks] and modified for our needs.
597 // FIXME: It would be nice to eventually to share this code somehow.
598 - (BOOL)_canUseResourceForRequest:(NSURLRequest *)theRequest
599 {
600     NSURLRequestCachePolicy policy = [theRequest cachePolicy];
601     
602     if (policy == NSURLRequestReturnCacheDataElseLoad) {
603         return YES;
604     } else if (policy == NSURLRequestReturnCacheDataDontLoad) {
605         return YES;
606     } else if (policy == NSURLRequestReloadIgnoringCacheData) {
607         return NO;
608     } else if ([theRequest valueForHTTPHeaderField:@"must-revalidate"] != nil) {
609         return NO;
610     } else if ([theRequest valueForHTTPHeaderField:@"proxy-revalidate"] != nil) {
611         return NO;
612     } else if ([theRequest valueForHTTPHeaderField:@"If-Modified-Since"] != nil) {
613         return NO;
614     } else if ([theRequest valueForHTTPHeaderField:@"Cache-Control"] != nil) {
615         return NO;
616     } else if (isCaseInsensitiveEqual(@"POST", [theRequest HTTPMethod])) {
617         return NO;
618     } else {
619         return YES;
620     }
621 }
622
623 - (BOOL)_canUseResourceWithResponse:(NSURLResponse *)theResponse
624 {
625     if (WKGetNSURLResponseMustRevalidate(theResponse)) {
626         return NO;
627     } else if (WKGetNSURLResponseCalculatedExpiration(theResponse) - CFAbsoluteTimeGetCurrent() < 1) {
628         return NO;
629     } else {
630         return YES;
631     }
632 }
633
634 - (NSMutableDictionary *)pendingArchivedResources
635 {
636     if (!pendingArchivedResources)
637         pendingArchivedResources = [[NSMutableDictionary alloc] init];
638     
639     return pendingArchivedResources;
640 }
641
642 - (BOOL)willUseArchiveForRequest:(NSURLRequest *)r originalURL:(NSURL *)originalURL loader:(WebLoader *)loader
643 {
644     if ([[r URL] isEqual:originalURL] && [self _canUseResourceForRequest:r]) {
645         WebResource *resource = [self _archivedSubresourceForURL:originalURL];
646         if (resource && [self _canUseResourceWithResponse:[resource _response]]) {
647             [[self pendingArchivedResources] _webkit_setObject:resource forUncopiedKey:loader];
648             // Deliver the resource after a delay because callers don't expect to receive callbacks while calling this method.
649             [self deliverArchivedResourcesAfterDelay];
650             return YES;
651         }
652     }
653     return NO;
654 }
655
656 - (BOOL)archiveLoadPendingForLoader:(WebLoader *)loader
657 {
658     return [pendingArchivedResources objectForKey:loader] != nil;
659 }
660
661 - (void)cancelPendingArchiveLoadForLoader:(WebLoader *)loader
662 {
663     [pendingArchivedResources removeObjectForKey:loader];
664     
665     if (![pendingArchivedResources count])
666         [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(deliverArchivedResources) object:nil];
667 }
668
669 - (void)_addExtraFieldsToRequest:(NSMutableURLRequest *)request mainResource:(BOOL)mainResource alwaysFromRequest:(BOOL)f
670 {
671     [webFrame _addExtraFieldsToRequest:request mainResource:mainResource alwaysFromRequest:f];
672 }
673
674 - (void)cannotShowMIMETypeForURL:(NSURL *)URL
675 {
676     [webFrame _handleUnimplementablePolicyWithErrorCode:WebKitErrorCannotShowMIMEType forURL:URL];    
677 }
678
679 - (NSError *)interruptForPolicyChangeErrorWithRequest:(NSURLRequest *)request
680 {
681     return [NSError _webKitErrorWithDomain:WebKitErrorDomain code:WebKitErrorFrameLoadInterruptedByPolicyChange URL:[request URL]];
682 }
683
684 - (BOOL)isHostedByObjectElement
685 {
686     // Handle <object> fallback for error cases.            
687     DOMHTMLElement *hostElement = [webFrame frameElement];
688     return hostElement && [hostElement isKindOfClass:[DOMHTMLObjectElement class]];
689 }
690
691 - (BOOL)isLoadingMainFrame
692 {
693     return [webFrame _isMainFrame];
694 }
695
696 + (BOOL)_canShowMIMEType:(NSString *)MIMEType
697 {
698     return [WebView canShowMIMEType:MIMEType];
699 }
700
701 + (BOOL)_representationExistsForURLScheme:(NSString *)URLScheme
702 {
703     return [WebView _representationExistsForURLScheme:URLScheme];
704 }
705
706 + (NSString *)_generatedMIMETypeForURLScheme:(NSString *)URLScheme
707 {
708     return [WebView _generatedMIMETypeForURLScheme:URLScheme];
709 }
710
711 - (void)_checkNavigationPolicyForRequest:(NSURLRequest *)newRequest andCall:(id)obj withSelector:(SEL)sel
712 {
713     [webFrame _checkNavigationPolicyForRequest:newRequest
714                                     dataSource:[self activeDataSource]
715                                      formState:nil
716                                        andCall:obj
717                                   withSelector:sel];
718 }
719
720 - (void)_checkContentPolicyForMIMEType:(NSString *)MIMEType andCall:(id)obj withSelector:(SEL)sel
721 {
722     WebPolicyDecisionListener *l = [[WebPolicyDecisionListener alloc] _initWithTarget:obj action:sel];
723     listener = l;
724     
725     [l retain];
726     [[self activeDataSource] _decidePolicyForMIMEType:MIMEType decisionListener:l];
727     [l release];
728 }
729
730 - (void)cancelContentPolicy
731 {
732     [listener _invalidate];
733     [listener release];
734     listener = nil;
735 }
736
737 - (void)_loadRequest:(NSURLRequest *)request archive:(WebArchive *)archive
738 {
739     WebFrameLoadType loadType;
740     
741     policyDocumentLoadState = [webFrame _createDocumentLoadStateWithRequest:request];
742     WebDataSource *newDataSource = [webFrame _dataSourceForDocumentLoadState:policyDocumentLoadState];
743
744     NSMutableURLRequest *r = [newDataSource request];
745     [webFrame _addExtraFieldsToRequest:r mainResource:YES alwaysFromRequest:NO];
746     if ([webFrame _shouldTreatURLAsSameAsCurrent:[request URL]]) {
747         [r setCachePolicy:NSURLRequestReloadIgnoringCacheData];
748         loadType = WebFrameLoadTypeSame;
749     } else
750         loadType = WebFrameLoadTypeStandard;
751     
752     [newDataSource _setOverrideEncoding:[[self dataSource] _overrideEncoding]];
753     [newDataSource _addToUnarchiveState:archive];
754     
755     // When we loading alternate content for an unreachable URL that we're
756     // visiting in the b/f list, we treat it as a reload so the b/f list 
757     // is appropriately maintained.
758     if ([webFrame _shouldReloadToHandleUnreachableURLFromRequest:request]) {
759         ASSERT(loadType == WebFrameLoadTypeStandard);
760         loadType = WebFrameLoadTypeReload;
761     }
762     
763     [webFrame _loadDataSource:newDataSource withLoadType:loadType formState:nil];
764 }
765
766 - (void)_loadRequest:(NSURLRequest *)request triggeringAction:(NSDictionary *)action loadType:(WebFrameLoadType)loadType formState:(WebFormState *)formState
767 {
768     policyDocumentLoadState = [webFrame _createDocumentLoadStateWithRequest:request];
769     WebDataSource *newDataSource = [webFrame _dataSourceForDocumentLoadState:policyDocumentLoadState];
770
771     [newDataSource _setTriggeringAction:action];
772
773     [newDataSource _setOverrideEncoding:[[self dataSource] _overrideEncoding]];
774
775     [webFrame _loadDataSource:newDataSource withLoadType:loadType formState:formState];
776 }
777
778 - (void)_reloadAllowingStaleDataWithOverrideEncoding:(NSString *)encoding
779 {
780     WebDataSource *ds = [self dataSource];
781     if (ds == nil)
782         return;
783
784     NSMutableURLRequest *request = [[ds request] mutableCopy];
785     NSURL *unreachableURL = [ds unreachableURL];
786     if (unreachableURL != nil)
787         [request setURL:unreachableURL];
788
789     [request setCachePolicy:NSURLRequestReturnCacheDataElseLoad];
790     policyDocumentLoadState = [webFrame _createDocumentLoadStateWithRequest:request];
791     WebDataSource *newDataSource = [webFrame _dataSourceForDocumentLoadState:policyDocumentLoadState];
792     [request release];
793     
794     [newDataSource _setOverrideEncoding:encoding];
795
796     [webFrame _loadDataSource:newDataSource withLoadType:WebFrameLoadTypeReloadAllowingStaleData formState:nil];
797 }
798
799 - (void)reload
800 {
801     WebDataSource *ds = [self dataSource];
802     if (ds == nil)
803         return;
804
805     NSMutableURLRequest *initialRequest = [ds request];
806     
807     // If a window is created by javascript, its main frame can have an empty but non-nil URL.
808     // Reloading in this case will lose the current contents (see 4151001).
809     if ([[[[ds request] URL] absoluteString] length] == 0)
810         return;
811
812     // Replace error-page URL with the URL we were trying to reach.
813     NSURL *unreachableURL = [initialRequest _webDataRequestUnreachableURL];
814     if (unreachableURL != nil)
815         initialRequest = [NSURLRequest requestWithURL:unreachableURL];
816     
817     policyDocumentLoadState = [webFrame _createDocumentLoadStateWithRequest:initialRequest];
818     WebDataSource *newDataSource = [webFrame _dataSourceForDocumentLoadState:policyDocumentLoadState];
819     NSMutableURLRequest *request = [newDataSource request];
820
821     [request setCachePolicy:NSURLRequestReloadIgnoringCacheData];
822
823     // If we're about to rePOST, set up action so the app can warn the user
824     if ([[request HTTPMethod] _webkit_isCaseInsensitiveEqualToString:@"POST"]) {
825         NSDictionary *action = [webFrame _actionInformationForNavigationType:WebNavigationTypeFormResubmitted event:nil originalURL:[request URL]];
826         [newDataSource _setTriggeringAction:action];
827     }
828
829     [newDataSource _setOverrideEncoding:[ds _overrideEncoding]];
830     
831     [webFrame _loadDataSource:newDataSource withLoadType:WebFrameLoadTypeReload formState:nil];
832 }
833
834 - (void)didReceiveServerRedirectForProvisionalLoadForFrame
835 {
836     [webFrame _didReceiveServerRedirectForProvisionalLoadForFrame];
837 }
838
839 - (void)finishedLoadingDocumentLoadState:(WebDocumentLoadState *)loadState
840 {
841     [[webFrame _dataSourceForDocumentLoadState:loadState] _finishedLoading];
842 }
843
844 - (void)commitProvisitionalLoad
845 {
846     [webFrame _commitProvisionalLoad:nil];
847 }
848
849 - (void)committedLoadWithDocumentLoadState:(WebDocumentLoadState *)loadState data:(NSData *)data
850 {
851     [[webFrame _dataSourceForDocumentLoadState:loadState] _receivedData:data];
852 }
853
854 - (BOOL)isReplacing
855 {
856     return [webFrame _loadType] == WebFrameLoadTypeReplace;
857 }
858
859 - (void)setReplacing
860 {
861     [webFrame _setLoadType:WebFrameLoadTypeReplace];
862 }
863
864 - (void)revertToProvisionalWithDocumentLoadState:(WebDocumentLoadState *)loadState
865 {
866     [[webFrame _dataSourceForDocumentLoadState:loadState] _revertToProvisionalState];
867 }
868
869 - (void)documentLoadState:(WebDocumentLoadState *)loadState setMainDocumentError:(NSError *)error
870 {
871     [[webFrame _dataSourceForDocumentLoadState:loadState] _setMainDocumentError:error];
872 }
873
874 - (void)documentLoadState:(WebDocumentLoadState *)loadState mainReceivedCompleteError:(NSError *)error
875 {
876     [[webFrame _dataSourceForDocumentLoadState:loadState] _setPrimaryLoadComplete:YES];
877     [webFrame _checkLoadComplete];
878 }
879
880 - (void)finalSetupForReplaceWithDocumentLoadState:(WebDocumentLoadState *)loadState
881 {
882     [[webFrame _dataSourceForDocumentLoadState:loadState] _clearUnarchivingState];
883 }
884
885 @end