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