Rubber stamped by Maciej.
[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 "WebFrameLoader.h"
30
31 #import "WebDataProtocol.h"
32 #import "WebDataSourceInternal.h"
33 #import "WebDocumentLoaderMac.h"
34 #import "WebDownloadInternal.h"
35 #import "WebFrameBridge.h"
36 #import "WebFrameInternal.h"
37 #import "WebFrameLoadDelegate.h"
38 #import "WebHistory.h"
39 #import "WebIconDatabasePrivate.h"
40 #import "WebKitErrorsPrivate.h"
41 #import "WebKitLogging.h"
42 #import "WebKitNSStringExtras.h"
43 #import "WebMainResourceLoader.h"
44 #import "WebNSDictionaryExtras.h"
45 #import "WebNSURLExtras.h"
46 #import "WebPreferences.h"
47 #import "WebResourcePrivate.h"
48 #import "WebResourceLoadDelegate.h"
49 #import "WebDefaultResourceLoadDelegate.h"
50 #import "WebScriptDebugServerPrivate.h"
51 #import "WebViewInternal.h"
52 #import <JavaScriptCore/Assertions.h>
53 #import <WebKit/DOMHTML.h>
54
55 @implementation WebFrameLoader
56
57 - (id)initWithClient:(WebFrame <WebFrameLoaderClient> *)c
58 {
59     self = [super init];
60     if (self) {
61         client = c;
62         state = WebFrameStateCommittedPage;
63     }
64     return self;    
65 }
66
67 - (void)dealloc
68 {
69     // FIXME: should these even exist?
70     [mainResourceLoader release];
71     [subresourceLoaders release];
72     [plugInStreamLoaders release];
73     [documentLoader release];
74     [provisionalDocumentLoader release];
75  
76     ASSERT(!policyDocumentLoader);
77     
78     [super dealloc];
79 }
80
81 - (WebDocumentLoader *)activeDocumentLoader
82 {
83     if (state == WebFrameStateProvisional)
84         return provisionalDocumentLoader;
85     
86     return documentLoader;    
87 }
88
89 - (WebDataSource *)activeDataSource
90 {
91     return [client _dataSourceForDocumentLoader:[self activeDocumentLoader]];
92 }
93
94 - (WebResource *)_archivedSubresourceForURL:(NSURL *)URL
95 {
96     return [[self activeDataSource] _archivedSubresourceForURL:URL];
97 }
98
99 - (void)addPlugInStreamLoader:(WebLoader *)loader
100 {
101     if (!plugInStreamLoaders)
102         plugInStreamLoaders = [[NSMutableArray alloc] init];
103     [plugInStreamLoaders addObject:loader];
104     [[self activeDocumentLoader] setLoading:YES];
105 }
106
107 - (void)removePlugInStreamLoader:(WebLoader *)loader
108 {
109     [plugInStreamLoaders removeObject:loader];
110     [[self activeDocumentLoader] updateLoading];
111 }    
112
113 - (void)defersCallbacksChanged
114 {
115     [self setDefersCallbacks:[[client webView] defersCallbacks]];
116 }
117
118 - (BOOL)defersCallbacks
119 {
120     return [[client webView] defersCallbacks];
121 }
122
123 - (void)setDefersCallbacks:(BOOL)defers
124 {
125     [mainResourceLoader setDefersCallbacks:defers];
126     
127     NSEnumerator *e = [subresourceLoaders objectEnumerator];
128     WebLoader *loader;
129     while ((loader = [e nextObject]))
130         [loader setDefersCallbacks:defers];
131     
132     e = [plugInStreamLoaders objectEnumerator];
133     while ((loader = [e nextObject]))
134         [loader setDefersCallbacks:defers];
135
136     [self deliverArchivedResourcesAfterDelay];
137 }
138
139 - (void)stopLoadingPlugIns
140 {
141     [plugInStreamLoaders makeObjectsPerformSelector:@selector(cancel)];
142     [plugInStreamLoaders removeAllObjects];   
143 }
144
145 - (BOOL)isLoadingMainResource
146 {
147     return mainResourceLoader != nil;
148 }
149
150 - (BOOL)isLoadingSubresources
151 {
152     return [subresourceLoaders count];
153 }
154
155 - (BOOL)isLoadingPlugIns
156 {
157     return [plugInStreamLoaders count];
158 }
159
160 - (BOOL)isLoading
161 {
162     return [self isLoadingMainResource] || [self isLoadingSubresources] || [self isLoadingPlugIns];
163 }
164
165 - (void)stopLoadingSubresources
166 {
167     NSArray *loaders = [subresourceLoaders copy];
168     [loaders makeObjectsPerformSelector:@selector(cancel)];
169     [loaders release];
170     [subresourceLoaders removeAllObjects];
171 }
172
173 - (void)addSubresourceLoader:(WebLoader *)loader
174 {
175     ASSERT(!provisionalDocumentLoader);
176     if (subresourceLoaders == nil)
177         subresourceLoaders = [[NSMutableArray alloc] init];
178     [subresourceLoaders addObject:loader];
179     [[self activeDocumentLoader] setLoading:YES];
180 }
181
182 - (void)removeSubresourceLoader:(WebLoader *)loader
183 {
184     [subresourceLoaders removeObject:loader];
185     [[self activeDocumentLoader] updateLoading];
186 }
187
188 - (NSData *)mainResourceData
189 {
190     return [mainResourceLoader resourceData];
191 }
192
193 - (void)releaseMainResourceLoader
194 {
195     [mainResourceLoader release];
196     mainResourceLoader = nil;
197 }
198
199 - (void)cancelMainResourceLoad
200 {
201     [mainResourceLoader cancel];
202 }
203
204 - (BOOL)startLoadingMainResourceWithRequest:(NSMutableURLRequest *)request identifier:(id)identifier
205 {
206     mainResourceLoader = [[WebMainResourceLoader alloc] initWithFrameLoader:self];
207     
208     [mainResourceLoader setIdentifier:identifier];
209     [client _addExtraFieldsToRequest:request mainResource:YES alwaysFromRequest:NO];
210     if (![mainResourceLoader loadWithRequest:request]) {
211         // FIXME: if this should really be caught, we should just ASSERT this doesn't happen;
212         // should it be caught by other parts of WebKit or other parts of the app?
213         LOG_ERROR("could not create WebResourceHandle for URL %@ -- should be caught by policy handler level", [request URL]);
214         [mainResourceLoader release];
215         mainResourceLoader = nil;
216         return NO;
217     }
218     
219     return YES;
220 }
221
222 - (void)stopLoadingWithError:(NSError *)error
223 {
224     [mainResourceLoader cancelWithError:error];
225 }
226
227 - (WebDataSource *)dataSource
228 {
229     return [client _dataSourceForDocumentLoader:documentLoader]; 
230 }
231
232 - (void)setDocumentLoader:(WebDocumentLoader *)loader
233 {
234     if (loader == nil && documentLoader == nil)
235         return;
236     
237     ASSERT(loader != documentLoader);
238     
239     [client _prepareForDataSourceReplacement];
240     [documentLoader detachFromFrameLoader];
241     
242     [loader retain];
243     [documentLoader release];
244     documentLoader = loader;
245 }
246
247 - (WebDocumentLoader *)documentLoader
248 {
249     return documentLoader;
250 }
251
252 - (WebDataSource *)policyDataSource
253 {
254     return [client _dataSourceForDocumentLoader:policyDocumentLoader];     
255 }
256
257 - (void)setPolicyDocumentLoader:(WebDocumentLoader *)loader
258 {
259     if (policyDocumentLoader == loader)
260         return;
261
262     if (policyDocumentLoader != provisionalDocumentLoader && policyDocumentLoader != documentLoader)
263         [policyDocumentLoader detachFromFrameLoader];
264
265     [policyDocumentLoader release];
266     [loader retain];
267     policyDocumentLoader = loader;
268 }
269    
270 - (void)clearDataSource
271 {
272     [self setDocumentLoader:nil];
273 }
274
275 - (WebDataSource *)provisionalDataSource 
276 {
277     return [client _dataSourceForDocumentLoader:provisionalDocumentLoader]; 
278 }
279
280 - (WebDocumentLoader *)provisionalDocumentLoader
281 {
282     return provisionalDocumentLoader;
283 }
284
285 - (void)setProvisionalDocumentLoader:(WebDocumentLoader *)loader
286 {
287     ASSERT(!loader || !provisionalDocumentLoader);
288
289     if (provisionalDocumentLoader != documentLoader)
290         [provisionalDocumentLoader detachFromFrameLoader];
291
292     [loader retain];
293     [provisionalDocumentLoader release];
294     provisionalDocumentLoader = loader;
295 }
296
297 - (void)_clearProvisionalDataSource
298 {
299     [self setProvisionalDocumentLoader:nil];
300 }
301
302 - (WebFrameState)state
303 {
304     return state;
305 }
306
307 #ifndef NDEBUG
308 static const char * const stateNames[] = {
309     "WebFrameStateProvisional",
310     "WebFrameStateCommittedPage",
311     "WebFrameStateComplete"
312 };
313 #endif
314
315 static CFAbsoluteTime _timeOfLastCompletedLoad;
316
317 + (CFAbsoluteTime)timeOfLastCompletedLoad
318 {
319     return _timeOfLastCompletedLoad;
320 }
321
322 - (void)_setState:(WebFrameState)newState
323 {
324     LOG(Loading, "%@:  transition from %s to %s", [client name], stateNames[state], stateNames[newState]);
325     if ([client webView])
326         LOG(Timing, "%@:  transition from %s to %s, %f seconds since start of document load", [client name], stateNames[state], stateNames[newState], CFAbsoluteTimeGetCurrent() - [[[[[client webView] mainFrame] dataSource] _documentLoader] loadingStartedTime]);
327     
328     if (newState == WebFrameStateComplete && client == [[client webView] mainFrame])
329         LOG(DocumentLoad, "completed %@ (%f seconds)", [[[self dataSource] request] URL], CFAbsoluteTimeGetCurrent() - [[[self dataSource] _documentLoader] loadingStartedTime]);
330     
331     state = newState;
332     
333     if (state == WebFrameStateProvisional)
334         [client _provisionalLoadStarted];
335     else if (state == WebFrameStateComplete) {
336         [client _frameLoadCompleted];
337         _timeOfLastCompletedLoad = CFAbsoluteTimeGetCurrent();
338         [[self documentLoader] stopRecordingResponses];
339     }
340 }
341
342 - (void)clearProvisionalLoad
343 {
344     [self setProvisionalDocumentLoader:nil];
345     [[client webView] _progressCompleted:client];
346     [self _setState:WebFrameStateComplete];
347 }
348
349 - (void)markLoadComplete
350 {
351     [self _setState:WebFrameStateComplete];
352 }
353
354 - (void)commitProvisionalLoad
355 {
356     [self stopLoadingSubresources];
357     [self stopLoadingPlugIns];
358
359     [self setDocumentLoader:provisionalDocumentLoader];
360     [self setProvisionalDocumentLoader:nil];
361     [self _setState:WebFrameStateCommittedPage];
362 }
363
364 - (void)stopLoading
365 {
366     [[self provisionalDocumentLoader] stopLoading];
367     [[self documentLoader] stopLoading];
368     [self _clearProvisionalDataSource];
369     [self clearArchivedResources];
370 }
371
372 // FIXME: poor method name; also why is this not part of startProvisionalLoad:?
373 - (void)startLoading
374 {
375     [provisionalDocumentLoader prepareForLoadStart];
376         
377     if ([self isLoadingMainResource])
378         return;
379         
380     [[self provisionalDataSource] _setLoadingFromPageCache:NO];
381         
382     id identifier;
383     id resourceLoadDelegate = [[client webView] resourceLoadDelegate];
384     if ([resourceLoadDelegate respondsToSelector:@selector(webView:identifierForInitialRequest:fromDataSource:)])
385         identifier = [resourceLoadDelegate webView:[client webView] identifierForInitialRequest:[provisionalDocumentLoader originalRequest] fromDataSource:[self provisionalDataSource]];
386     else
387         identifier = [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:[client webView] identifierForInitialRequest:[provisionalDocumentLoader originalRequest] fromDataSource:[self provisionalDataSource]];
388     
389     if (![[provisionalDocumentLoader frameLoader] startLoadingMainResourceWithRequest:[provisionalDocumentLoader actualRequest] identifier:identifier])
390         [provisionalDocumentLoader updateLoading];
391 }
392
393 - (void)startProvisionalLoad:(WebDataSource *)ds
394 {
395     [self setProvisionalDocumentLoader:[ds _documentLoader]];
396     [self _setState:WebFrameStateProvisional];
397 }
398
399 - (void)setupForReplace
400 {
401     [self _setState:WebFrameStateProvisional];
402     WebDocumentLoader *old = provisionalDocumentLoader;
403     provisionalDocumentLoader = documentLoader;
404     documentLoader = nil;
405     [old release];
406     
407     [client _detachChildren];
408 }
409
410 - (id)_identifierForInitialRequest:(NSURLRequest *)clientRequest
411 {
412     WebView *webView = [client webView];
413         
414     // The identifier is released after the last callback, rather than in dealloc
415     // to avoid potential cycles.
416     if ([webView _resourceLoadDelegateImplementations].delegateImplementsIdentifierForRequest)
417         return [[[webView resourceLoadDelegate] webView:webView identifierForInitialRequest:clientRequest fromDataSource:[self activeDataSource]] retain];
418     else
419         return [[[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView identifierForInitialRequest:clientRequest fromDataSource:[self activeDataSource]] retain];
420 }
421
422 - (NSURLRequest *)_willSendRequest:(NSMutableURLRequest *)clientRequest forResource:(id)identifier redirectResponse:(NSURLResponse *)redirectResponse
423 {
424     WebView *webView = [client webView];
425     
426     [clientRequest setValue:[webView userAgentForURL:[clientRequest URL]] forHTTPHeaderField:@"User-Agent"];
427     
428     if ([webView _resourceLoadDelegateImplementations].delegateImplementsWillSendRequest)
429         return [[webView resourceLoadDelegate] webView:webView resource:identifier willSendRequest:clientRequest redirectResponse:redirectResponse fromDataSource:[self activeDataSource]];
430     else
431         return [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier willSendRequest:clientRequest redirectResponse:redirectResponse fromDataSource:[self activeDataSource]];
432 }
433
434 - (void)_didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)currentWebChallenge forResource:(id)identifier
435 {
436     WebView *webView = [client webView];
437     
438     if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidReceiveAuthenticationChallenge)
439         [[webView resourceLoadDelegate] webView:webView resource:identifier didReceiveAuthenticationChallenge:currentWebChallenge fromDataSource:[self activeDataSource]];
440     else
441         [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didReceiveAuthenticationChallenge:currentWebChallenge fromDataSource:[self activeDataSource]];
442 }
443
444 - (void)_didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)currentWebChallenge forResource:(id)identifier
445 {
446     WebView *webView = [client webView];
447     
448     if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidCancelAuthenticationChallenge)
449         [[webView resourceLoadDelegate] webView:webView resource:identifier didCancelAuthenticationChallenge:currentWebChallenge fromDataSource:[self activeDataSource]];
450     else
451         [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didCancelAuthenticationChallenge:currentWebChallenge fromDataSource:[self activeDataSource]];
452     
453 }
454
455 - (void)_didReceiveResponse:(NSURLResponse *)r forResource:(id)identifier
456 {
457     WebView *webView = [client webView];
458     
459     [[self activeDocumentLoader] addResponse:r];
460     
461     [webView _incrementProgressForIdentifier:identifier response:r];
462     
463     if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidReceiveResponse)
464         [[webView resourceLoadDelegate] webView:webView resource:identifier didReceiveResponse:r fromDataSource:[self activeDataSource]];
465     else
466         [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didReceiveResponse:r fromDataSource:[self activeDataSource]];
467 }
468
469 - (void)_didReceiveData:(NSData *)data contentLength:(int)lengthReceived forResource:(id)identifier
470 {
471     WebView *webView = [client webView];
472     
473     [webView _incrementProgressForIdentifier:identifier data:data];
474     
475     if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidReceiveContentLength)
476         [[webView resourceLoadDelegate] webView:webView resource:identifier didReceiveContentLength:(WebNSUInteger)lengthReceived fromDataSource:[self activeDataSource]];
477     else
478         [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didReceiveContentLength:(WebNSUInteger)lengthReceived fromDataSource:[self activeDataSource]];
479 }
480
481 - (void)_didFinishLoadingForResource:(id)identifier
482 {    
483     WebView *webView = [client webView];
484     
485     [webView _completeProgressForIdentifier:identifier];    
486     
487     if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidFinishLoadingFromDataSource)
488         [[webView resourceLoadDelegate] webView:webView resource:identifier didFinishLoadingFromDataSource:[self activeDataSource]];
489     else
490         [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didFinishLoadingFromDataSource:[self activeDataSource]];
491 }
492
493 - (void)_didFailLoadingWithError:(NSError *)error forResource:(id)identifier
494 {
495     WebView *webView = [client webView];
496         
497     [webView _completeProgressForIdentifier:identifier];
498         
499     if (error)
500         [[webView _resourceLoadDelegateForwarder] webView:webView resource:identifier didFailLoadingWithError:error fromDataSource:[self activeDataSource]];
501 }
502
503 - (BOOL)_privateBrowsingEnabled
504 {
505     return [[[client webView] preferences] privateBrowsingEnabled];
506 }
507
508 - (void)_finishedLoadingResource
509 {
510     [client _checkLoadComplete];
511 }
512
513 - (void)_receivedError:(NSError *)error
514 {
515     [client _checkLoadComplete];
516 }
517
518 - (NSURLRequest *)_originalRequest
519 {
520     return [[self activeDocumentLoader] originalRequestCopy];
521 }
522
523 - (WebFrame *)webFrame
524 {
525     return client;
526 }
527
528 - (void)_receivedMainResourceError:(NSError *)error complete:(BOOL)isComplete
529 {
530     WebDocumentLoader *loader = [self activeDocumentLoader];
531     [loader retain];
532     
533     WebFrameBridge *bridge = [client _bridge];
534     
535     // Retain the bridge because the stop may release the last reference to it.
536     [bridge retain];
537  
538     WebFrame *cli = [client retain];
539    
540     if (isComplete) {
541         // FIXME: Don't want to do this if an entirely new load is going, so should check
542         // that both data sources on the frame are either self or nil.
543         // Can't call [self _bridge] because we might not have commited yet
544         [bridge stop];
545         // FIXME: WebKitErrorPlugInWillHandleLoad is a workaround for the cancel we do to prevent loading plugin content twice.  See <rdar://problem/4258008>
546         if ([error code] != NSURLErrorCancelled && [error code] != WebKitErrorPlugInWillHandleLoad)
547             [bridge handleFallbackContent];
548     }
549     
550     [bridge release];
551     
552     [cli _receivedMainResourceError:error];
553     [loader mainReceivedError:error complete:isComplete];
554
555     [cli release];
556
557     [loader release];
558 }
559
560 - (NSURLRequest *)initialRequest
561 {
562     return [[self activeDataSource] initialRequest];
563 }
564
565 - (void)_receivedData:(NSData *)data
566 {
567     [[self activeDocumentLoader] receivedData:data];
568 }
569
570 - (void)_setRequest:(NSURLRequest *)request
571 {
572     [[self activeDocumentLoader] setRequest:request];
573 }
574
575 - (void)_downloadWithLoadingConnection:(NSURLConnection *)connection request:(NSURLRequest *)request response:(NSURLResponse *)r proxy:(id)proxy
576 {
577     [WebDownload _downloadWithLoadingConnection:connection
578                                         request:request
579                                        response:r
580                                        delegate:[[client webView] downloadDelegate]
581                                           proxy:proxy];
582 }
583
584 - (WebFrameBridge *)bridge
585 {
586     return [client _bridge];
587 }
588
589 - (void)_handleFallbackContent
590 {
591     [[self bridge] handleFallbackContent];
592 }
593
594 - (BOOL)_isStopping
595 {
596     return [[self activeDocumentLoader] isStopping];
597 }
598
599 - (void)_setupForReplaceByMIMEType:(NSString *)newMIMEType
600 {
601     [[self activeDocumentLoader] setupForReplaceByMIMEType:newMIMEType];
602 }
603
604 - (void)_setResponse:(NSURLResponse *)response
605 {
606     [[self activeDocumentLoader] setResponse:response];
607 }
608
609 - (void)_mainReceivedError:(NSError *)error complete:(BOOL)isComplete
610 {
611     [[self activeDocumentLoader] mainReceivedError:error complete:isComplete];
612 }
613
614 - (void)_finishedLoading
615 {
616     WebDataSource *ds = [self activeDataSource];
617     
618     [self retain];
619     [[self activeDocumentLoader] finishedLoading];
620
621     if ([ds _mainDocumentError] || ![ds webFrame]) {
622         [self release];
623         return;
624     }
625
626     [[self activeDocumentLoader] setPrimaryLoadComplete:YES];
627     if ([WebScriptDebugServer listenerCount])
628         [[WebScriptDebugServer sharedScriptDebugServer] webView:[client webView] didLoadMainResourceForDataSource:[self activeDataSource]];
629     [client _checkLoadComplete];
630
631     [self release];
632 }
633
634 - (void)_notifyIconChanged:(NSURL *)iconURL
635 {
636     ASSERT([[WebIconDatabase sharedIconDatabase] _isEnabled]);
637     ASSERT(client == [[client webView] mainFrame]);
638
639     [[client webView] _willChangeValueForKey:_WebMainFrameIconKey];
640     
641     NSImage *icon = [[WebIconDatabase sharedIconDatabase] iconForURL:[[[self activeDataSource] _URL] _web_originalDataAsString] withSize:WebIconSmallSize];
642     
643     [[[client webView] _frameLoadDelegateForwarder] webView:[client webView]
644                                                didReceiveIcon:icon
645                                                      forFrame:client];
646     
647     [[client webView] _didChangeValueForKey:_WebMainFrameIconKey];
648 }
649
650 - (NSURL *)_URL
651 {
652     return [[self activeDataSource] _URL];
653 }
654
655 - (NSError *)cancelledErrorWithRequest:(NSURLRequest *)request
656 {
657     return [NSError _webKitErrorWithDomain:NSURLErrorDomain
658                                       code:NSURLErrorCancelled
659                                        URL:[request URL]];
660 }
661
662 - (NSError *)fileDoesNotExistErrorWithResponse:(NSURLResponse *)response
663 {
664     return [NSError _webKitErrorWithDomain:NSURLErrorDomain
665                                                 code:NSURLErrorFileDoesNotExist
666                                                  URL:[response URL]];    
667 }
668
669 - (void)clearArchivedResources
670 {
671     [pendingArchivedResources removeAllObjects];
672     [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(deliverArchivedResources) object:nil];
673 }
674
675 - (void)deliverArchivedResources
676 {
677     if (![pendingArchivedResources count] || [self defersCallbacks])
678         return;
679         
680     NSEnumerator *keyEnum = [pendingArchivedResources keyEnumerator];
681     WebLoader *loader;
682     while ((loader = [keyEnum nextObject])) {
683         WebResource *resource = [pendingArchivedResources objectForKey:loader];
684         [loader didReceiveResponse:[resource _response]];
685         NSData *data = [resource data];
686         [loader didReceiveData:data lengthReceived:[data length] allAtOnce:YES];
687         [loader didFinishLoading];
688     }
689     
690     [pendingArchivedResources removeAllObjects];
691 }
692
693 - (void)deliverArchivedResourcesAfterDelay
694 {
695     if (![pendingArchivedResources count] || [self defersCallbacks])
696         return;
697     
698     [self performSelector:@selector(deliverArchivedResources) withObject:nil afterDelay:0];
699 }
700
701 static BOOL isCaseInsensitiveEqual(NSString *a, NSString *b)
702 {
703     return [a caseInsensitiveCompare:b] == NSOrderedSame;
704 }
705
706 // The following 2 methods are copied from [NSHTTPURLProtocol _cachedResponsePassesValidityChecks] and modified for our needs.
707 // FIXME: It would be nice to eventually to share this code somehow.
708 - (BOOL)_canUseResourceForRequest:(NSURLRequest *)theRequest
709 {
710     NSURLRequestCachePolicy policy = [theRequest cachePolicy];
711     
712     if (policy == NSURLRequestReturnCacheDataElseLoad) {
713         return YES;
714     } else if (policy == NSURLRequestReturnCacheDataDontLoad) {
715         return YES;
716     } else if (policy == NSURLRequestReloadIgnoringCacheData) {
717         return NO;
718     } else if ([theRequest valueForHTTPHeaderField:@"must-revalidate"] != nil) {
719         return NO;
720     } else if ([theRequest valueForHTTPHeaderField:@"proxy-revalidate"] != nil) {
721         return NO;
722     } else if ([theRequest valueForHTTPHeaderField:@"If-Modified-Since"] != nil) {
723         return NO;
724     } else if ([theRequest valueForHTTPHeaderField:@"Cache-Control"] != nil) {
725         return NO;
726     } else if (isCaseInsensitiveEqual(@"POST", [theRequest HTTPMethod])) {
727         return NO;
728     } else {
729         return YES;
730     }
731 }
732
733 - (BOOL)_canUseResourceWithResponse:(NSURLResponse *)theResponse
734 {
735     if (WKGetNSURLResponseMustRevalidate(theResponse)) {
736         return NO;
737     } else if (WKGetNSURLResponseCalculatedExpiration(theResponse) - CFAbsoluteTimeGetCurrent() < 1) {
738         return NO;
739     } else {
740         return YES;
741     }
742 }
743
744 - (NSMutableDictionary *)pendingArchivedResources
745 {
746     if (!pendingArchivedResources)
747         pendingArchivedResources = [[NSMutableDictionary alloc] init];
748     
749     return pendingArchivedResources;
750 }
751
752 - (BOOL)willUseArchiveForRequest:(NSURLRequest *)r originalURL:(NSURL *)originalURL loader:(WebLoader *)loader
753 {
754     if ([[r URL] isEqual:originalURL] && [self _canUseResourceForRequest:r]) {
755         WebResource *resource = [self _archivedSubresourceForURL:originalURL];
756         if (resource && [self _canUseResourceWithResponse:[resource _response]]) {
757             [[self pendingArchivedResources] _webkit_setObject:resource forUncopiedKey:loader];
758             // Deliver the resource after a delay because callers don't expect to receive callbacks while calling this method.
759             [self deliverArchivedResourcesAfterDelay];
760             return YES;
761         }
762     }
763     return NO;
764 }
765
766 - (BOOL)archiveLoadPendingForLoader:(WebLoader *)loader
767 {
768     return [pendingArchivedResources objectForKey:loader] != nil;
769 }
770
771 - (void)cancelPendingArchiveLoadForLoader:(WebLoader *)loader
772 {
773     [pendingArchivedResources removeObjectForKey:loader];
774     
775     if (![pendingArchivedResources count])
776         [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(deliverArchivedResources) object:nil];
777 }
778
779 - (void)_addExtraFieldsToRequest:(NSMutableURLRequest *)request mainResource:(BOOL)mainResource alwaysFromRequest:(BOOL)f
780 {
781     [client _addExtraFieldsToRequest:request mainResource:mainResource alwaysFromRequest:f];
782 }
783
784 - (void)cannotShowMIMETypeForURL:(NSURL *)URL
785 {
786     [self handleUnimplementablePolicyWithErrorCode:WebKitErrorCannotShowMIMEType forURL:URL];    
787 }
788
789 - (NSError *)interruptForPolicyChangeErrorWithRequest:(NSURLRequest *)request
790 {
791     return [NSError _webKitErrorWithDomain:WebKitErrorDomain code:WebKitErrorFrameLoadInterruptedByPolicyChange URL:[request URL]];
792 }
793
794 - (BOOL)isHostedByObjectElement
795 {
796     // Handle <object> fallback for error cases.            
797     DOMHTMLElement *hostElement = [client frameElement];
798     return hostElement && [hostElement isKindOfClass:[DOMHTMLObjectElement class]];
799 }
800
801 - (BOOL)isLoadingMainFrame
802 {
803     return [client _isMainFrame];
804 }
805
806 + (BOOL)_canShowMIMEType:(NSString *)MIMEType
807 {
808     return [WebView canShowMIMEType:MIMEType];
809 }
810
811 + (BOOL)_representationExistsForURLScheme:(NSString *)URLScheme
812 {
813     return [WebView _representationExistsForURLScheme:URLScheme];
814 }
815
816 + (NSString *)_generatedMIMETypeForURLScheme:(NSString *)URLScheme
817 {
818     return [WebView _generatedMIMETypeForURLScheme:URLScheme];
819 }
820
821 - (void)_checkNavigationPolicyForRequest:(NSURLRequest *)newRequest andCall:(id)obj withSelector:(SEL)sel
822 {
823     [self checkNavigationPolicyForRequest:newRequest
824                               dataSource:[self activeDataSource]
825                                 formState:nil
826                                   andCall:obj
827                              withSelector:sel];
828 }
829
830 - (void)_checkContentPolicyForMIMEType:(NSString *)MIMEType andCall:(id)obj withSelector:(SEL)sel
831 {
832     WebPolicyDecisionListener *l = [[WebPolicyDecisionListener alloc] _initWithTarget:obj action:sel];
833     listener = l;
834     
835     [l retain];
836
837     [[[client webView] _policyDelegateForwarder] webView:[client webView] decidePolicyForMIMEType:MIMEType
838                                                  request:[[self activeDocumentLoader] request]
839                                                    frame:client
840                                         decisionListener:listener];
841     [l release];
842 }
843
844 - (void)cancelContentPolicy
845 {
846     [listener _invalidate];
847     [listener release];
848     listener = nil;
849 }
850
851 static inline BOOL isBackForwardLoadType(WebFrameLoadType type)
852 {
853     switch (type) {
854         case WebFrameLoadTypeStandard:
855         case WebFrameLoadTypeReload:
856         case WebFrameLoadTypeReloadAllowingStaleData:
857         case WebFrameLoadTypeSame:
858         case WebFrameLoadTypeInternal:
859         case WebFrameLoadTypeReplace:
860             return false;
861         case WebFrameLoadTypeBack:
862         case WebFrameLoadTypeForward:
863         case WebFrameLoadTypeIndexedBackForward:
864             return true;
865     }
866     ASSERT_NOT_REACHED();
867     return false;
868 }
869
870 - (BOOL)shouldReloadToHandleUnreachableURLFromRequest:(NSURLRequest *)request
871 {
872     NSURL *unreachableURL = [request _webDataRequestUnreachableURL];
873     if (unreachableURL == nil)
874         return NO;
875     
876     if (!isBackForwardLoadType(policyLoadType))
877         return NO;
878     
879     // We only treat unreachableURLs specially during the delegate callbacks
880     // for provisional load errors and navigation policy decisions. The former
881     // case handles well-formed URLs that can't be loaded, and the latter
882     // case handles malformed URLs and unknown schemes. Loading alternate content
883     // at other times behaves like a standard load.
884     WebDataSource *compareDataSource = nil;
885     if (delegateIsDecidingNavigationPolicy || delegateIsHandlingUnimplementablePolicy)
886         compareDataSource = [self policyDataSource];
887     else if (delegateIsHandlingProvisionalLoadError)
888         compareDataSource = [self provisionalDataSource];
889     
890     return compareDataSource != nil && [unreachableURL isEqual:[[compareDataSource request] URL]];
891 }
892
893 - (void)_loadRequest:(NSURLRequest *)request archive:(WebArchive *)archive
894 {
895     WebFrameLoadType type;
896     
897     ASSERT(!policyDocumentLoader);
898     policyDocumentLoader = [client _createDocumentLoaderWithRequest:request];
899     WebDataSource *newDataSource = [client _dataSourceForDocumentLoader:policyDocumentLoader];
900
901     NSMutableURLRequest *r = [newDataSource request];
902     [client _addExtraFieldsToRequest:r mainResource:YES alwaysFromRequest:NO];
903     if ([client _shouldTreatURLAsSameAsCurrent:[request URL]]) {
904         [r setCachePolicy:NSURLRequestReloadIgnoringCacheData];
905         type = WebFrameLoadTypeSame;
906     } else
907         type = WebFrameLoadTypeStandard;
908     
909     [policyDocumentLoader setOverrideEncoding:[[self documentLoader] overrideEncoding]];
910     [newDataSource _addToUnarchiveState:archive];
911     
912     // When we loading alternate content for an unreachable URL that we're
913     // visiting in the b/f list, we treat it as a reload so the b/f list 
914     // is appropriately maintained.
915     if ([self shouldReloadToHandleUnreachableURLFromRequest:request]) {
916         ASSERT(type == WebFrameLoadTypeStandard);
917         type = WebFrameLoadTypeReload;
918     }
919     
920     [self loadDataSource:newDataSource withLoadType:type formState:nil];
921 }
922
923 - (void)_loadRequest:(NSURLRequest *)request triggeringAction:(NSDictionary *)action loadType:(WebFrameLoadType)type formState:(WebFormState *)formState
924 {
925     ASSERT(!policyDocumentLoader);
926     policyDocumentLoader = [client _createDocumentLoaderWithRequest:request];
927     WebDataSource *newDataSource = [client _dataSourceForDocumentLoader:policyDocumentLoader];
928
929     [policyDocumentLoader setTriggeringAction:action];
930     [policyDocumentLoader setOverrideEncoding:[[self documentLoader] overrideEncoding]];
931
932     [self loadDataSource:newDataSource withLoadType:type formState:formState];
933 }
934
935 - (void)_reloadAllowingStaleDataWithOverrideEncoding:(NSString *)encoding
936 {
937     WebDataSource *ds = [self dataSource];
938     if (ds == nil)
939         return;
940
941     NSMutableURLRequest *request = [[ds request] mutableCopy];
942     NSURL *unreachableURL = [ds unreachableURL];
943     if (unreachableURL != nil)
944         [request setURL:unreachableURL];
945
946     [request setCachePolicy:NSURLRequestReturnCacheDataElseLoad];
947     ASSERT(!policyDocumentLoader);
948     policyDocumentLoader = [client _createDocumentLoaderWithRequest:request];
949     WebDataSource *newDataSource = [client _dataSourceForDocumentLoader:policyDocumentLoader];
950     [request release];
951     
952     [policyDocumentLoader setOverrideEncoding:encoding];
953
954     [self loadDataSource:newDataSource withLoadType:WebFrameLoadTypeReloadAllowingStaleData formState:nil];
955 }
956
957 - (void)reload
958 {
959     WebDataSource *ds = [self dataSource];
960     if (ds == nil)
961         return;
962
963     NSMutableURLRequest *initialRequest = [ds request];
964     
965     // If a window is created by javascript, its main frame can have an empty but non-nil URL.
966     // Reloading in this case will lose the current contents (see 4151001).
967     if ([[[[ds request] URL] absoluteString] length] == 0)
968         return;
969
970     // Replace error-page URL with the URL we were trying to reach.
971     NSURL *unreachableURL = [initialRequest _webDataRequestUnreachableURL];
972     if (unreachableURL != nil)
973         initialRequest = [NSURLRequest requestWithURL:unreachableURL];
974     
975     ASSERT(!policyDocumentLoader);
976     policyDocumentLoader = [client _createDocumentLoaderWithRequest:initialRequest];
977     WebDataSource *newDataSource = [client _dataSourceForDocumentLoader:policyDocumentLoader];
978     NSMutableURLRequest *request = [newDataSource request];
979
980     [request setCachePolicy:NSURLRequestReloadIgnoringCacheData];
981
982     // If we're about to rePOST, set up action so the app can warn the user
983     if ([[request HTTPMethod] _webkit_isCaseInsensitiveEqualToString:@"POST"]) {
984         NSDictionary *action = [client _actionInformationForNavigationType:WebNavigationTypeFormResubmitted event:nil originalURL:[request URL]];
985         [policyDocumentLoader setTriggeringAction:action];
986     }
987
988     [policyDocumentLoader setOverrideEncoding:[[ds _documentLoader] overrideEncoding]];
989     
990     [self loadDataSource:newDataSource withLoadType:WebFrameLoadTypeReload formState:nil];
991 }
992
993 - (void)didReceiveServerRedirectForProvisionalLoadForFrame
994 {
995     [client _didReceiveServerRedirectForProvisionalLoadForFrame];
996 }
997
998 - (void)finishedLoadingDocument:(WebDocumentLoader *)loader
999 {
1000     [[client _dataSourceForDocumentLoader:loader] _finishedLoading];
1001 }
1002
1003 - (void)commitProvisitionalLoad
1004 {
1005     [client _commitProvisionalLoad:nil];
1006 }
1007
1008 - (void)committedLoadWithDocumentLoader:(WebDocumentLoader *)loader data:(NSData *)data
1009 {
1010     [[client _dataSourceForDocumentLoader:loader] _receivedData:data];
1011 }
1012
1013 - (BOOL)isReplacing
1014 {
1015     return loadType == WebFrameLoadTypeReplace;
1016 }
1017
1018 - (void)setReplacing
1019 {
1020     loadType = WebFrameLoadTypeReplace;
1021 }
1022
1023 - (void)revertToProvisionalWithDocumentLoader:(WebDocumentLoader *)loader
1024 {
1025     [[client _dataSourceForDocumentLoader:loader] _revertToProvisionalState];
1026 }
1027
1028 - (void)documentLoader:(WebDocumentLoader *)loader setMainDocumentError:(NSError *)error
1029 {
1030     [[client _dataSourceForDocumentLoader:loader] _setMainDocumentError:error];
1031 }
1032
1033 - (void)documentLoader:(WebDocumentLoader *)loader mainReceivedCompleteError:(NSError *)error
1034 {
1035     [loader setPrimaryLoadComplete:YES];
1036     if ([WebScriptDebugServer listenerCount])
1037         [[WebScriptDebugServer sharedScriptDebugServer] webView:[client webView] didLoadMainResourceForDataSource:[self activeDataSource]];
1038     [client _checkLoadComplete];
1039 }
1040
1041 - (void)finalSetupForReplaceWithDocumentLoader:(WebDocumentLoader *)loader
1042 {
1043     [[client _dataSourceForDocumentLoader:loader] _clearUnarchivingState];
1044 }
1045
1046 - (void)prepareForLoadStart
1047 {
1048     [[client webView] _progressStarted:client];
1049     [[client webView] _didStartProvisionalLoadForFrame:client];
1050     [[[client webView] _frameLoadDelegateForwarder] webView:[client webView]
1051                                didStartProvisionalLoadForFrame:client];    
1052 }
1053
1054 - (BOOL)subframeIsLoading
1055 {
1056     return [client _subframeIsLoading];
1057 }
1058
1059 - (void)willChangeTitleForDocument:(WebDocumentLoader *)loader
1060 {
1061     // FIXME: should do this only in main frame case, right?
1062     [[client webView] _willChangeValueForKey:_WebMainFrameTitleKey];
1063 }
1064
1065 - (void)didChangeTitleForDocument:(WebDocumentLoader *)loader
1066 {
1067     // FIXME: should do this only in main frame case, right?
1068     [[client webView] _didChangeValueForKey:_WebMainFrameTitleKey];
1069
1070     // The title doesn't get communicated to the WebView until we are committed.
1071     if ([loader isCommitted]) {
1072         NSURL *URLForHistory = [[client _dataSourceForDocumentLoader:loader] _URLForHistory];
1073         if (URLForHistory != nil) {
1074             WebHistoryItem *entry = [[WebHistory optionalSharedHistory] itemForURL:URLForHistory];
1075             [entry setTitle:[loader title]];
1076         
1077             // Must update the entries in the back-forward list too.  This must go through the WebFrame because
1078             // it has the right notion of the current b/f item.
1079             [client _setTitle:[loader title]];
1080         
1081             [[client webView] setMainFrameDocumentReady:YES];    // update observers with new DOMDocument
1082             [[[client webView] _frameLoadDelegateForwarder] webView:[client webView]
1083                                                       didReceiveTitle:[loader title]
1084                                                              forFrame:client];
1085         }
1086     }
1087 }
1088
1089 - (WebFrameLoadType)loadType
1090 {
1091     return loadType;
1092 }
1093
1094 - (void)setLoadType:(WebFrameLoadType)type
1095 {
1096     loadType = type;
1097 }
1098
1099 - (void)invalidatePendingPolicyDecisionCallingDefaultAction:(BOOL)call
1100 {
1101     [listener _invalidate];
1102     [listener release];
1103     listener = nil;
1104
1105     NSURLRequest *request = policyRequest;
1106     NSString *frameName = policyFrameName;
1107     id target = policyTarget;
1108     SEL selector = policySelector;
1109     WebFormState *formState = policyFormState;
1110
1111     policyRequest = nil;
1112     policyFrameName = nil;
1113     policyTarget = nil;
1114     policySelector = nil;
1115     policyFormState = nil;
1116
1117     if (call) {
1118         if (frameName)
1119             objc_msgSend(target, selector, nil, nil, nil);
1120         else
1121             objc_msgSend(target, selector, nil, nil);
1122     }
1123
1124     [request release];
1125     [frameName release];
1126     [target release];
1127     [formState release];
1128 }
1129
1130 - (void)checkNewWindowPolicyForRequest:(NSURLRequest *)request action:(NSDictionary *)action frameName:(NSString *)frameName formState:(WebFormState *)formState andCall:(id)target withSelector:(SEL)selector
1131 {
1132     WebPolicyDecisionListener *decisionListener = [[WebPolicyDecisionListener alloc]
1133         _initWithTarget:self action:@selector(_continueAfterNewWindowPolicy:)];
1134
1135     policyRequest = [request retain];
1136     policyTarget = [target retain];
1137     policyFrameName = [frameName retain];
1138     policySelector = selector;
1139     listener = [decisionListener retain];
1140     policyFormState = [formState retain];
1141
1142     WebView *wv = [client webView];
1143     [[wv _policyDelegateForwarder] webView:wv
1144             decidePolicyForNewWindowAction:action
1145                                    request:request
1146                               newFrameName:frameName
1147                           decisionListener:decisionListener];
1148     
1149     [decisionListener release];
1150 }
1151
1152 - (void)_continueAfterNewWindowPolicy:(WebPolicyAction)policy
1153 {
1154     NSURLRequest *request = [[policyRequest retain] autorelease];
1155     NSString *frameName = [[policyFrameName retain] autorelease];
1156     id target = [[policyTarget retain] autorelease];
1157     SEL selector = policySelector;
1158     WebFormState *formState = [[policyFormState retain] autorelease];
1159
1160     // will release policy* objects, hence the above retains
1161     [self invalidatePendingPolicyDecisionCallingDefaultAction:NO];
1162
1163     BOOL shouldContinue = NO;
1164
1165     switch (policy) {
1166     case WebPolicyIgnore:
1167         break;
1168     case WebPolicyDownload:
1169         // FIXME: should download full request
1170         [[client webView] _downloadURL:[request URL]];
1171         break;
1172     case WebPolicyUse:
1173         shouldContinue = YES;
1174         break;
1175     default:
1176         ASSERT_NOT_REACHED();
1177     }
1178
1179     objc_msgSend(target, selector, shouldContinue ? request : nil, frameName, formState);
1180 }
1181
1182 - (void)checkNavigationPolicyForRequest:(NSURLRequest *)request
1183                              dataSource:(WebDataSource *)dataSource
1184                               formState:(WebFormState *)formState
1185                                 andCall:(id)target
1186                            withSelector:(SEL)selector
1187 {
1188     NSDictionary *action = [[dataSource _documentLoader] triggeringAction];
1189     if (action == nil) {
1190         action = [client _actionInformationForNavigationType:WebNavigationTypeOther event:nil originalURL:[request URL]];
1191         [[dataSource _documentLoader]  setTriggeringAction:action];
1192     }
1193         
1194     // Don't ask more than once for the same request or if we are loading an empty URL.
1195     // This avoids confusion on the part of the client.
1196     if ([request isEqual:[[dataSource _documentLoader] lastCheckedRequest]] || [[request URL] _web_isEmpty]) {
1197         [target performSelector:selector withObject:request withObject:nil];
1198         return;
1199     }
1200     
1201     // We are always willing to show alternate content for unreachable URLs;
1202     // treat it like a reload so it maintains the right state for b/f list.
1203     if ([request _webDataRequestUnreachableURL] != nil) {
1204         if (isBackForwardLoadType(policyLoadType))
1205             policyLoadType = WebFrameLoadTypeReload;
1206         [target performSelector:selector withObject:request withObject:nil];
1207         return;
1208     }
1209     
1210     [[dataSource _documentLoader] setLastCheckedRequest:request];
1211
1212     WebPolicyDecisionListener *decisionListener = [[WebPolicyDecisionListener alloc] _initWithTarget:self action:@selector(continueAfterNavigationPolicy:)];
1213     
1214     ASSERT(policyRequest == nil);
1215     policyRequest = [request retain];
1216     ASSERT(policyTarget == nil);
1217     policyTarget = [target retain];
1218     policySelector = selector;
1219     ASSERT(listener == nil);
1220     listener = [decisionListener retain];
1221     ASSERT(policyFormState == nil);
1222     policyFormState = [formState retain];
1223
1224     WebView *wv = [client webView];
1225     delegateIsDecidingNavigationPolicy = YES;
1226     [[wv _policyDelegateForwarder] webView:wv
1227            decidePolicyForNavigationAction:action
1228                                    request:request
1229                                      frame:client
1230                           decisionListener:decisionListener];
1231     delegateIsDecidingNavigationPolicy = NO;
1232     
1233     [decisionListener release];
1234 }
1235
1236 - (void)continueAfterNavigationPolicy:(WebPolicyAction)policy
1237 {
1238     NSURLRequest *request = [[policyRequest retain] autorelease];
1239     id target = [[policyTarget retain] autorelease];
1240     SEL selector = policySelector;
1241     WebFormState *formState = [[policyFormState retain] autorelease];
1242     
1243     // will release policy* objects, hence the above retains
1244     [self invalidatePendingPolicyDecisionCallingDefaultAction:NO];
1245
1246     BOOL shouldContinue = NO;
1247
1248     switch (policy) {
1249     case WebPolicyIgnore:
1250         break;
1251     case WebPolicyDownload:
1252         // FIXME: should download full request
1253         [[client webView] _downloadURL:[request URL]];
1254         break;
1255     case WebPolicyUse:
1256         if (![WebView _canHandleRequest:request]) {
1257             [self handleUnimplementablePolicyWithErrorCode:WebKitErrorCannotShowURL forURL:[request URL]];
1258         } else {
1259             shouldContinue = YES;
1260         }
1261         break;
1262     default:
1263         ASSERT_NOT_REACHED();
1264     }
1265
1266     [target performSelector:selector withObject:(shouldContinue ? request : nil) withObject:formState];
1267 }
1268
1269 // Called after the FormsDelegate is done processing willSubmitForm:
1270 - (void)continueAfterWillSubmitForm:(WebPolicyAction)policy
1271 {
1272     if (listener) {
1273         [listener _invalidate];
1274         [listener release];
1275         listener = nil;
1276     }
1277     [self startLoading];
1278 }
1279
1280 - (void)continueLoadRequestAfterNavigationPolicy:(NSURLRequest *)request formState:(WebFormState *)formState
1281 {
1282     // If we loaded an alternate page to replace an unreachableURL, we'll get in here with a
1283     // nil policyDataSource because loading the alternate page will have passed
1284     // through this method already, nested; otherwise, policyDataSource should still be set.
1285     ASSERT([self policyDataSource] || [[self provisionalDataSource] unreachableURL] != nil);
1286
1287     BOOL isTargetItem = [client _provisionalItemIsTarget];
1288
1289     // Two reasons we can't continue:
1290     //    1) Navigation policy delegate said we can't so request is nil. A primary case of this 
1291     //       is the user responding Cancel to the form repost nag sheet.
1292     //    2) User responded Cancel to an alert popped up by the before unload event handler.
1293     // The "before unload" event handler runs only for the main frame.
1294     BOOL canContinue = request && ([[client webView] mainFrame] != client || [[self bridge] shouldClose]);
1295
1296     if (!canContinue) {
1297         // If we were waiting for a quick redirect, but the policy delegate decided to ignore it, then we 
1298         // need to report that the client redirect was cancelled.
1299         if ([client _quickRedirectComing])
1300             [client _clientRedirectCancelledOrFinished:NO];
1301
1302         [self setPolicyDocumentLoader:nil];
1303
1304         // If the navigation request came from the back/forward menu, and we punt on it, we have the 
1305         // problem that we have optimistically moved the b/f cursor already, so move it back.  For sanity, 
1306         // we only do this when punting a navigation for the target frame or top-level frame.  
1307         if ((isTargetItem || [[client webView] mainFrame] == client) && isBackForwardLoadType(policyLoadType))
1308             [(WebFrame <WebFrameLoaderClient> *)[[client webView] mainFrame] _resetBackForwardList];
1309
1310         return;
1311     }
1312     
1313     WebFrameLoadType type = policyLoadType;
1314     WebDataSource *dataSource = [[self policyDataSource] retain];
1315     
1316     [self stopLoading];
1317     loadType = type;
1318
1319     [self startProvisionalLoad:dataSource];
1320
1321     [dataSource release];
1322     [self setPolicyDocumentLoader:nil];
1323     
1324     if (client == [[client webView] mainFrame])
1325         LOG(DocumentLoad, "loading %@", [[[self provisionalDataSource] request] URL]);
1326
1327     if (type == WebFrameLoadTypeForward || type == WebFrameLoadTypeBack || type == WebFrameLoadTypeIndexedBackForward) {
1328         if ([client _loadProvisionalItemFromPageCache])
1329             return;
1330     }
1331
1332     if (formState) {
1333         // It's a bit of a hack to reuse the WebPolicyDecisionListener for the continuation
1334         // mechanism across the willSubmitForm callout.
1335         listener = [[WebPolicyDecisionListener alloc] _initWithTarget:self action:@selector(continueAfterWillSubmitForm:)];
1336         [[[client webView] _formDelegate] frame:client sourceFrame:[formState sourceFrame] willSubmitForm:[formState form] withValues:[formState values] submissionListener:listener];
1337     } 
1338     else {
1339         [self continueAfterWillSubmitForm:WebPolicyUse];
1340     }
1341 }
1342
1343 - (void)loadDataSource:(WebDataSource *)newDataSource withLoadType:(WebFrameLoadType)type formState:(WebFormState *)formState
1344 {
1345     ASSERT([client webView] != nil);
1346
1347     // Unfortunately the view must be non-nil, this is ultimately due
1348     // to parser requiring a FrameView.  We should fix this dependency.
1349
1350     ASSERT([client frameView] != nil);
1351
1352     policyLoadType = type;
1353
1354     WebDocumentLoaderMac *loader = (WebDocumentLoaderMac *)[newDataSource _documentLoader];
1355
1356     WebFrame *parentFrame = [client parentFrame];
1357     if (parentFrame)
1358         [loader setOverrideEncoding:[[[parentFrame dataSource] _documentLoader] overrideEncoding]];
1359
1360     [loader setFrameLoader:self];
1361     [loader setDataSource:newDataSource];
1362
1363     [self invalidatePendingPolicyDecisionCallingDefaultAction:YES];
1364
1365     [self setPolicyDocumentLoader:loader];
1366
1367     [self checkNavigationPolicyForRequest:[newDataSource request]
1368                                dataSource:newDataSource
1369                                 formState:formState
1370                                   andCall:self
1371                              withSelector:@selector(continueLoadRequestAfterNavigationPolicy:formState:)];
1372 }
1373
1374 - (void)handleUnimplementablePolicyWithErrorCode:(int)code forURL:(NSURL *)URL
1375 {
1376     NSError *error = [NSError _webKitErrorWithDomain:WebKitErrorDomain code:code URL:URL];
1377     WebView *wv = [client webView];
1378     delegateIsHandlingUnimplementablePolicy = YES;
1379     [[wv _policyDelegateForwarder] webView:wv unableToImplementPolicyWithError:error frame:client];    
1380     delegateIsHandlingUnimplementablePolicy = NO;
1381 }
1382
1383 - (BOOL)delegateIsHandlingProvisionalLoadError
1384 {
1385     return delegateIsHandlingProvisionalLoadError;
1386 }
1387
1388 - (void)setDelegateIsHandlingProvisionalLoadError:(BOOL)is
1389 {
1390     delegateIsHandlingProvisionalLoadError = is;
1391 }
1392
1393 - (void)didFirstLayout
1394 {
1395     if ([[client webView] backForwardList]) {
1396         if (loadType == WebFrameLoadTypeForward || loadType == WebFrameLoadTypeBack || loadType == WebFrameLoadTypeIndexedBackForward)
1397             [client _restoreScrollPositionAndViewState];
1398     }
1399     
1400     firstLayoutDone = YES;
1401
1402     WebView *wv = [client webView];
1403     [[wv _frameLoadDelegateForwarder] webView:wv didFirstLayoutInFrame:client];
1404 }
1405
1406 - (void)provisionalLoadStarted
1407 {
1408     firstLayoutDone = NO;
1409 }
1410
1411 - (void)frameLoadCompleted
1412 {
1413     // After a canceled provisional load, firstLayoutDone is NO. Reset it to YES if we're displaying a page.
1414     if ([self dataSource])
1415         firstLayoutDone = YES;
1416 }
1417
1418 - (BOOL)firstLayoutDone
1419 {
1420     return firstLayoutDone;
1421 }
1422
1423 @end