f06eee277a5de4af9454dfb063a3efd177b462ad
[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 "WebDocumentLoader.h"
33 #import "WebFormDataStream.h"
34 #import "WebFrameBridge.h"
35 #import "WebFrameLoaderClient.h"
36 #import "WebMainResourceLoader.h"
37 #import <JavaScriptCore/Assertions.h>
38 #import <WebKit/DOMHTML.h>
39 #import <WebCore/WebCoreSystemInterface.h>
40
41 #import "WebDataSourceInternal.h"
42 #import "WebDocumentLoaderMac.h"
43 #import "WebFrameInternal.h"
44 #import "WebFrameViewInternal.h"
45 #import "WebHTMLView.h"
46 #import "WebIconDatabasePrivate.h"
47 #import "WebKitErrorsPrivate.h"
48 #import "WebKitLogging.h"
49 #import "WebNSURLExtras.h"
50 #import "WebNSURLRequestExtras.h"
51 #import "WebResourcePrivate.h"
52 #import "WebScriptDebugServerPrivate.h"
53 #import "WebViewInternal.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 - (void)addPlugInStreamLoader:(WebLoader *)loader
95 {
96     if (!plugInStreamLoaders)
97         plugInStreamLoaders = [[NSMutableArray alloc] init];
98     [plugInStreamLoaders addObject:loader];
99     [[self activeDocumentLoader] setLoading:YES];
100 }
101
102 - (void)removePlugInStreamLoader:(WebLoader *)loader
103 {
104     [plugInStreamLoaders removeObject:loader];
105     [[self activeDocumentLoader] updateLoading];
106 }    
107
108 - (void)defersCallbacksChanged
109 {
110     BOOL defers = [[client webView] defersCallbacks];
111     for (WebFrame *frame = client; frame; frame = [frame _traverseNextFrameStayWithin:client])
112         [[frame _frameLoader] setDefersCallbacks:defers];
113 }
114
115 - (BOOL)defersCallbacks
116 {
117     return [[client webView] defersCallbacks];
118 }
119
120 - (void)setDefersCallbacks:(BOOL)defers
121 {
122     [mainResourceLoader setDefersCallbacks:defers];
123     
124     NSEnumerator *e = [subresourceLoaders objectEnumerator];
125     WebLoader *loader;
126     while ((loader = [e nextObject]))
127         [loader setDefersCallbacks:defers];
128     
129     e = [plugInStreamLoaders objectEnumerator];
130     while ((loader = [e nextObject]))
131         [loader setDefersCallbacks:defers];
132
133     [self deliverArchivedResourcesAfterDelay];
134 }
135
136 - (void)stopLoadingPlugIns
137 {
138     [plugInStreamLoaders makeObjectsPerformSelector:@selector(cancel)];
139     [plugInStreamLoaders removeAllObjects];   
140 }
141
142 - (BOOL)isLoadingMainResource
143 {
144     return mainResourceLoader != nil;
145 }
146
147 - (BOOL)isLoadingSubresources
148 {
149     return [subresourceLoaders count];
150 }
151
152 - (BOOL)isLoadingPlugIns
153 {
154     return [plugInStreamLoaders count];
155 }
156
157 - (BOOL)isLoading
158 {
159     return [self isLoadingMainResource] || [self isLoadingSubresources] || [self isLoadingPlugIns];
160 }
161
162 - (void)stopLoadingSubresources
163 {
164     NSArray *loaders = [subresourceLoaders copy];
165     [loaders makeObjectsPerformSelector:@selector(cancel)];
166     [loaders release];
167     [subresourceLoaders removeAllObjects];
168 }
169
170 - (void)addSubresourceLoader:(WebLoader *)loader
171 {
172     ASSERT(!provisionalDocumentLoader);
173     if (subresourceLoaders == nil)
174         subresourceLoaders = [[NSMutableArray alloc] init];
175     [subresourceLoaders addObject:loader];
176     [[self activeDocumentLoader] setLoading:YES];
177 }
178
179 - (void)removeSubresourceLoader:(WebLoader *)loader
180 {
181     [subresourceLoaders removeObject:loader];
182     [[self activeDocumentLoader] updateLoading];
183 }
184
185 - (NSData *)mainResourceData
186 {
187     return [mainResourceLoader resourceData];
188 }
189
190 - (void)releaseMainResourceLoader
191 {
192     [mainResourceLoader release];
193     mainResourceLoader = nil;
194 }
195
196 - (void)cancelMainResourceLoad
197 {
198     [mainResourceLoader cancel];
199 }
200
201 - (BOOL)startLoadingMainResourceWithRequest:(NSMutableURLRequest *)request identifier:(id)identifier
202 {
203     mainResourceLoader = [[WebMainResourceLoader alloc] initWithFrameLoader:self];
204     
205     [mainResourceLoader setIdentifier:identifier];
206     [self addExtraFieldsToRequest:request mainResource:YES alwaysFromRequest:NO];
207     if (![mainResourceLoader loadWithRequest:request]) {
208         // FIXME: if this should really be caught, we should just ASSERT this doesn't happen;
209         // should it be caught by other parts of WebKit or other parts of the app?
210         LOG_ERROR("could not create WebResourceHandle for URL %@ -- should be caught by policy handler level", [request URL]);
211         [mainResourceLoader release];
212         mainResourceLoader = nil;
213         return NO;
214     }
215     
216     return YES;
217 }
218
219 - (void)stopLoadingWithError:(NSError *)error
220 {
221     [mainResourceLoader cancelWithError:error];
222 }
223
224 - (WebDataSource *)dataSource
225 {
226     return [client _dataSourceForDocumentLoader:documentLoader]; 
227 }
228
229 - (void)setDocumentLoader:(WebDocumentLoader *)loader
230 {
231     if (loader == nil && documentLoader == nil)
232         return;
233     
234     ASSERT(loader != documentLoader);
235     
236     [client _prepareForDataSourceReplacement];
237     [documentLoader detachFromFrameLoader];
238     
239     [loader retain];
240     [documentLoader release];
241     documentLoader = loader;
242 }
243
244 - (WebDocumentLoader *)documentLoader
245 {
246     return documentLoader;
247 }
248
249 - (WebDataSource *)policyDataSource
250 {
251     return [client _dataSourceForDocumentLoader:policyDocumentLoader];     
252 }
253
254 - (void)setPolicyDocumentLoader:(WebDocumentLoader *)loader
255 {
256     if (policyDocumentLoader == loader)
257         return;
258
259     if (policyDocumentLoader != provisionalDocumentLoader && policyDocumentLoader != documentLoader)
260         [policyDocumentLoader detachFromFrameLoader];
261
262     [policyDocumentLoader release];
263     [loader retain];
264     policyDocumentLoader = loader;
265 }
266    
267 - (WebDataSource *)provisionalDataSource 
268 {
269     return [client _dataSourceForDocumentLoader:provisionalDocumentLoader]; 
270 }
271
272 - (WebDocumentLoader *)provisionalDocumentLoader
273 {
274     return provisionalDocumentLoader;
275 }
276
277 - (void)setProvisionalDocumentLoader:(WebDocumentLoader *)loader
278 {
279     ASSERT(!loader || !provisionalDocumentLoader);
280
281     if (provisionalDocumentLoader != documentLoader)
282         [provisionalDocumentLoader detachFromFrameLoader];
283
284     [loader retain];
285     [provisionalDocumentLoader release];
286     provisionalDocumentLoader = loader;
287 }
288
289 - (WebFrameState)state
290 {
291     return state;
292 }
293
294 #if !LOG_DISABLED
295 static const char * const stateNames[] = {
296     "WebFrameStateProvisional",
297     "WebFrameStateCommittedPage",
298     "WebFrameStateComplete"
299 };
300 #endif
301
302 static CFAbsoluteTime _timeOfLastCompletedLoad;
303
304 + (CFAbsoluteTime)timeOfLastCompletedLoad
305 {
306     return _timeOfLastCompletedLoad;
307 }
308
309 - (void)provisionalLoadStarted
310 {
311     firstLayoutDone = NO;
312     [[client _bridge] provisionalLoadStarted];
313
314     [client _provisionalLoadStarted];
315 }
316
317 - (void)setState:(WebFrameState)newState
318 {
319     LOG(Loading, "%@:  transition from %s to %s", [client name], stateNames[state], stateNames[newState]);
320     if ([client webView])
321         LOG(Timing, "%@:  transition from %s to %s, %f seconds since start of document load",
322             [client name], stateNames[state], stateNames[newState],
323             CFAbsoluteTimeGetCurrent() - [[[[[client webView] mainFrame] dataSource] _documentLoader] loadingStartedTime]);
324     
325     if (newState == WebFrameStateComplete && client == [[client webView] mainFrame])
326         LOG(DocumentLoad, "completed %@ (%f seconds)", [[[self dataSource] request] URL], CFAbsoluteTimeGetCurrent() - [[[self dataSource] _documentLoader] loadingStartedTime]);
327     
328     state = newState;
329     
330     if (state == WebFrameStateProvisional)
331         [self provisionalLoadStarted];
332     else if (state == WebFrameStateComplete) {
333         [self frameLoadCompleted];
334         _timeOfLastCompletedLoad = CFAbsoluteTimeGetCurrent();
335         [[self documentLoader] stopRecordingResponses];
336     }
337 }
338
339 - (void)clearProvisionalLoad
340 {
341     [self setProvisionalDocumentLoader:nil];
342     [[client webView] _progressCompleted:client];
343     [self setState:WebFrameStateComplete];
344 }
345
346 - (void)markLoadComplete
347 {
348     [self setState:WebFrameStateComplete];
349 }
350
351 - (void)commitProvisionalLoad
352 {
353     [self stopLoadingSubresources];
354     [self stopLoadingPlugIns];
355
356     [self setDocumentLoader:provisionalDocumentLoader];
357     [self setProvisionalDocumentLoader:nil];
358     [self setState:WebFrameStateCommittedPage];
359 }
360
361 - (void)stopLoadingSubframes
362 {
363     for (WebCoreFrameBridge *child = [[client _bridge] firstChild]; child; child = [child nextSibling])
364         [[(WebFrameBridge *)child frameLoader] stopLoading];
365 }
366
367 - (void)stopLoading
368 {
369     // If this method is called from within this method, infinite recursion can occur (3442218). Avoid this.
370     if (isStoppingLoad)
371         return;
372     
373     isStoppingLoad = YES;
374     
375     [self invalidatePendingPolicyDecisionCallingDefaultAction:YES];
376     
377     [self stopLoadingSubframes];
378     [provisionalDocumentLoader stopLoading];
379     [documentLoader stopLoading];
380     [self setProvisionalDocumentLoader:nil];
381     [self clearArchivedResources];
382
383     isStoppingLoad = NO;    
384 }
385
386 // FIXME: poor method name; also why is this not part of startProvisionalLoad:?
387 - (void)startLoading
388 {
389     [provisionalDocumentLoader prepareForLoadStart];
390         
391     if ([self isLoadingMainResource])
392         return;
393         
394     [[self provisionalDataSource] _setLoadingFromPageCache:NO];
395
396     id identifier = [client _dispatchIdentifierForInitialRequest:[provisionalDocumentLoader originalRequest] fromDocumentLoader:provisionalDocumentLoader];
397         
398     if (![self startLoadingMainResourceWithRequest:[provisionalDocumentLoader actualRequest] identifier:identifier])
399         [provisionalDocumentLoader updateLoading];
400 }
401
402 - (void)startProvisionalLoad:(WebDataSource *)ds
403 {
404     [self setProvisionalDocumentLoader:[ds _documentLoader]];
405     [self setState:WebFrameStateProvisional];
406 }
407
408 - (void)setupForReplace
409 {
410     [self setState:WebFrameStateProvisional];
411     WebDocumentLoader *old = provisionalDocumentLoader;
412     provisionalDocumentLoader = documentLoader;
413     documentLoader = nil;
414     [old release];
415     
416     [self detachChildren];
417 }
418
419 - (id)_identifierForInitialRequest:(NSURLRequest *)clientRequest
420 {
421     // FIXME: why retain here, but not in the other place this happens?
422
423     // The identifier is released after the last callback, rather than in dealloc,
424     // to avoid potential cycles.    
425     return [[client _dispatchIdentifierForInitialRequest:clientRequest fromDocumentLoader:[self activeDocumentLoader]] retain];
426 }
427
428 - (NSURLRequest *)_willSendRequest:(NSMutableURLRequest *)clientRequest forResource:(id)identifier redirectResponse:(NSURLResponse *)redirectResponse
429 {
430     WebView *webView = [client webView];
431     [clientRequest setValue:[webView userAgentForURL:[clientRequest URL]] forHTTPHeaderField:@"User-Agent"];
432     return [client _dispatchResource:identifier willSendRequest:clientRequest redirectResponse:redirectResponse fromDocumentLoader:[self activeDocumentLoader]];
433 }
434
435 - (void)_didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)currentWebChallenge forResource:(id)identifier
436 {
437     [client _dispatchDidReceiveAuthenticationChallenge:currentWebChallenge forResource:identifier fromDocumentLoader:[self activeDocumentLoader]];
438 }
439
440 - (void)_didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)currentWebChallenge forResource:(id)identifier
441 {
442     [client _dispatchDidCancelAuthenticationChallenge:currentWebChallenge forResource:identifier fromDocumentLoader:[self activeDocumentLoader]];
443 }
444
445 - (void)_didReceiveResponse:(NSURLResponse *)r forResource:(id)identifier
446 {
447     [[self activeDocumentLoader] addResponse:r];
448     
449     [[client webView] _incrementProgressForIdentifier:identifier response:r];
450     [client _dispatchResource:identifier didReceiveResponse:r fromDocumentLoader:[self activeDocumentLoader]];
451 }
452
453 - (void)_didReceiveData:(NSData *)data contentLength:(int)lengthReceived forResource:(id)identifier
454 {
455     WebView *webView = [client webView];
456     [webView _incrementProgressForIdentifier:identifier data:data];
457
458     [client _dispatchResource:identifier didReceiveContentLength:lengthReceived fromDocumentLoader:[self activeDocumentLoader]];
459 }
460
461 - (void)_didFinishLoadingForResource:(id)identifier
462 {    
463     WebView *webView = [client webView];
464     [webView _completeProgressForIdentifier:identifier];
465     [client _dispatchResource:identifier didFinishLoadingFromDocumentLoader:[self activeDocumentLoader]];
466 }
467
468 - (void)_didFailLoadingWithError:(NSError *)error forResource:(id)identifier
469 {
470     WebView *webView = [client webView];
471         
472     [webView _completeProgressForIdentifier:identifier];
473         
474     if (error)
475         [client _dispatchResource:identifier didFailLoadingWithError:error fromDocumentLoader:[self activeDocumentLoader]];
476 }
477
478 - (BOOL)_privateBrowsingEnabled
479 {
480     return [client _privateBrowsingEnabled];
481 }
482
483 - (void)_finishedLoadingResource
484 {
485     [self checkLoadComplete];
486 }
487
488 - (void)_receivedError:(NSError *)error
489 {
490     [self checkLoadComplete];
491 }
492
493 - (NSURLRequest *)_originalRequest
494 {
495     return [[self activeDocumentLoader] originalRequestCopy];
496 }
497
498 - (WebFrame *)webFrame
499 {
500     return client;
501 }
502
503 - (void)_receivedMainResourceError:(NSError *)error complete:(BOOL)isComplete
504 {
505     WebDocumentLoader *loader = [self activeDocumentLoader];
506     [loader retain];
507     
508     WebFrameBridge *bridge = [client _bridge];
509     
510     // Retain the bridge because the stop may release the last reference to it.
511     [bridge retain];
512  
513     WebFrame *cli = [client retain];
514    
515     if (isComplete) {
516         // FIXME: Don't want to do this if an entirely new load is going, so should check
517         // that both data sources on the frame are either self or nil.
518         // Can't call _bridge because we might not have commited yet
519         [bridge stop];
520         // FIXME: WebKitErrorPlugInWillHandleLoad is a workaround for the cancel we do to prevent loading plugin content twice.  See <rdar://problem/4258008>
521         if ([error code] != NSURLErrorCancelled && [error code] != WebKitErrorPlugInWillHandleLoad)
522             [bridge handleFallbackContent];
523     }
524     
525     if ([self state] == WebFrameStateProvisional) {
526         NSURL *failedURL = [[provisionalDocumentLoader originalRequestCopy] URL];
527         [bridge didNotOpenURL:failedURL];
528         [client _invalidateCurrentItemPageCache];
529         
530         // Call -_clientRedirectCancelledOrFinished: here so that the frame load delegate is notified that the redirect's
531         // status has changed, if there was a redirect.  The frame load delegate may have saved some state about
532         // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:.  Since we are definitely
533         // not going to use this provisional resource, as it was cancelled, notify the frame load delegate that the redirect
534         // has ended.
535         if (sentRedirectNotification)
536             [self clientRedirectCancelledOrFinished:NO];
537     }
538     
539     
540     [loader mainReceivedError:error complete:isComplete];
541
542     [bridge release];
543     [cli release];
544     [loader release];
545 }
546
547 - (void)clientRedirectCancelledOrFinished:(BOOL)cancelWithLoadInProgress
548 {
549     // Note that -webView:didCancelClientRedirectForFrame: is called on the frame load delegate even if
550     // the redirect succeeded.  We should either rename this API, or add a new method, like
551     // -webView:didFinishClientRedirectForFrame:
552     [client _dispatchDidCancelClientRedirectForFrame];
553
554     if (!cancelWithLoadInProgress)
555         quickRedirectComing = NO;
556     
557     sentRedirectNotification = NO;
558     
559     LOG(Redirect, "%@(%p) _private->quickRedirectComing = %d", [client name], self, (int)quickRedirectComing);
560 }
561
562 - (void)clientRedirectedTo:(NSURL *)URL delay:(NSTimeInterval)seconds fireDate:(NSDate *)date lockHistory:(BOOL)lockHistory isJavaScriptFormAction:(BOOL)isJavaScriptFormAction
563 {
564     LOG(Redirect, "%@(%p) Client redirect to: %@, [self dataSource] = %p, lockHistory = %d, isJavaScriptFormAction = %d", [client name], self, URL, [self dataSource], (int)lockHistory, (int)isJavaScriptFormAction);
565     
566     [client _dispatchWillPerformClientRedirectToURL:URL delay:seconds fireDate:date];
567     
568     // Remember that we sent a redirect notification to the frame load delegate so that when we commit
569     // the next provisional load, we can send a corresponding -webView:didCancelClientRedirectForFrame:
570     sentRedirectNotification = YES;
571     
572     // If a "quick" redirect comes in an, we set a special mode so we treat the next
573     // load as part of the same navigation.
574     
575     if (!documentLoader || isJavaScriptFormAction) {
576         // If we don't have a dataSource, we have no "original" load on which to base a redirect,
577         // so we better just treat the redirect as a normal load.
578         quickRedirectComing = NO;
579         LOG(Redirect, "%@(%p) _private->quickRedirectComing = %d", [client name], self, (int)quickRedirectComing);
580     } else {
581         quickRedirectComing = lockHistory;
582         LOG(Redirect, "%@(%p) _private->quickRedirectComing = %d", [client name], self, (int)quickRedirectComing);
583     }
584 }
585
586 - (BOOL)shouldReloadForCurrent:(NSURL *)currentURL andDestination:(NSURL *)destinationURL
587 {
588     return !(([currentURL fragment] || [destinationURL fragment]) &&
589              [[currentURL _webkit_URLByRemovingFragment] isEqual:[destinationURL _webkit_URLByRemovingFragment]]);
590 }
591
592 // main funnel for navigating via callback from WebCore (e.g., clicking a link, redirect)
593 - (void)loadURL:(NSURL *)URL referrer:(NSString *)referrer loadType:(FrameLoadType)_loadType target:(NSString *)target triggeringEvent:(NSEvent *)event form:(DOMElement *)form formValues:(NSDictionary *)values
594 {
595     BOOL isFormSubmission = (values != nil);
596     
597     NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:URL];
598     [request setValue:[[client webView] userAgentForURL:[request URL]] forHTTPHeaderField:@"Referer"];
599     [self addExtraFieldsToRequest:request mainResource:YES alwaysFromRequest:(event != nil || isFormSubmission)];
600     if (_loadType == FrameLoadTypeReload)
601         [request setCachePolicy:NSURLRequestReloadIgnoringCacheData];
602     
603     // I believe this is never called with LoadSame.  If it is, we probably want to set the cache
604     // policy of LoadFromOrigin, but I didn't test that.
605     ASSERT(_loadType != FrameLoadTypeSame);
606     
607     NSDictionary *action = [self actionInformationForLoadType:_loadType isFormSubmission:isFormSubmission event:event originalURL:URL];
608     WebFormState *formState = nil;
609     if (form && values)
610         formState = [[WebFormState alloc] initWithForm:form values:values sourceFrame:client];
611     
612     if (target != nil) {
613         WebFrame *targetFrame = [client findFrameNamed:target];
614         if (targetFrame != nil) {
615             [[targetFrame _frameLoader] loadURL:URL referrer:referrer loadType:_loadType target:nil triggeringEvent:event form:form formValues:values];
616         } else {
617             [self checkNewWindowPolicyForRequest:request
618                                           action:action
619                                        frameName:target
620                                        formState:formState
621                                          andCall:self
622                                     withSelector:@selector(continueLoadRequestAfterNewWindowPolicy:frameName:formState:)];
623         }
624         [request release];
625         [formState release];
626         return;
627     }
628     
629     WebDataSource *oldDataSource = [[self dataSource] retain];
630     
631     BOOL sameURL = [client _shouldTreatURLAsSameAsCurrent:URL];
632     
633     // Make sure to do scroll to anchor processing even if the URL is
634     // exactly the same so pages with '#' links and DHTML side effects
635     // work properly.
636     if (!isFormSubmission
637         && _loadType != FrameLoadTypeReload
638         && _loadType != FrameLoadTypeSame
639         && ![self shouldReloadForCurrent:URL andDestination:[[client _bridge] URL]]
640         
641         // We don't want to just scroll if a link from within a
642         // frameset is trying to reload the frameset into _top.
643         && ![[client _bridge] isFrameSet]) {
644         
645         // Just do anchor navigation within the existing content.
646         
647         // We don't do this if we are submitting a form, explicitly reloading,
648         // currently displaying a frameset, or if the new URL does not have a fragment.
649         // These rules are based on what KHTML was doing in KHTMLPart::openURL.
650         
651         // FIXME: What about load types other than Standard and Reload?
652         
653         [[oldDataSource _documentLoader] setTriggeringAction:action];
654         [self invalidatePendingPolicyDecisionCallingDefaultAction:YES];
655         [self checkNavigationPolicyForRequest:request
656                                                     dataSource:oldDataSource formState:formState
657                                                        andCall:self withSelector:@selector(continueFragmentScrollAfterNavigationPolicy:formState:)];
658     } else {
659         // must grab this now, since this load may stop the previous load and clear this flag
660         BOOL isRedirect = quickRedirectComing;
661         [self _loadRequest:request triggeringAction:action loadType:_loadType formState:formState];
662         if (isRedirect) {
663             LOG(Redirect, "%@(%p) _private->quickRedirectComing was %d", [client name], self, (int)isRedirect);
664             quickRedirectComing = NO;
665             [provisionalDocumentLoader setIsClientRedirect:YES];
666         } else if (sameURL) {
667             // Example of this case are sites that reload the same URL with a different cookie
668             // driving the generated content, or a master frame with links that drive a target
669             // frame, where the user has clicked on the same link repeatedly.
670             [self setLoadType:FrameLoadTypeSame];
671         }            
672     }
673     
674     [request release];
675     [oldDataSource release];
676     [formState release];
677 }
678
679 -(void)continueFragmentScrollAfterNavigationPolicy:(NSURLRequest *)request formState:(WebFormState *)formState
680 {
681     if (!request)
682         return;
683     
684     NSURL *URL = [request URL];
685     
686     BOOL isRedirect = quickRedirectComing;
687     LOG(Redirect, "%@(%p) _private->quickRedirectComing = %d", [client name], self, (int)quickRedirectComing);
688     quickRedirectComing = NO;
689     
690     [documentLoader replaceRequestURLForAnchorScrollWithURL:URL];
691     if (!isRedirect && ![client _shouldTreatURLAsSameAsCurrent:URL]) {
692         // NB: must happen after _setURL, since we add based on the current request.
693         // Must also happen before we openURL and displace the scroll position, since
694         // adding the BF item will save away scroll state.
695         
696         // NB2:  If we were loading a long, slow doc, and the user anchor nav'ed before
697         // it was done, currItem is now set the that slow doc, and prevItem is whatever was
698         // before it.  Adding the b/f item will bump the slow doc down to prevItem, even
699         // though its load is not yet done.  I think this all works out OK, for one because
700         // we have already saved away the scroll and doc state for the long slow load,
701         // but it's not an obvious case.
702
703         [client _addHistoryItemForFragmentScroll];
704     }
705     
706     [[client _bridge] scrollToAnchorWithURL:URL];
707     
708     if (!isRedirect) {
709         // This will clear previousItem from the rest of the frame tree tree that didn't
710         // doing any loading.  We need to make a pass on this now, since for anchor nav
711         // we'll not go through a real load and reach Completed state
712         [self checkLoadComplete];
713     }
714  
715     [client _dispatchDidChangeLocationWithinPageForFrame];
716     [client _didFinishLoad];
717 }
718
719 - (void)closeOldDataSources
720 {
721     // FIXME: is it important for this traversal to be postorder instead of preorder?
722     // FIXME: add helpers for postorder traversal?
723     for (WebCoreFrameBridge *child = [[client _bridge] firstChild]; child; child = [child nextSibling])
724         [[(WebFrameBridge *)child frameLoader] closeOldDataSources];
725     
726     if (documentLoader)
727         [client _dispatchWillCloseFrame];
728
729     [[client webView] setMainFrameDocumentReady:NO];  // stop giving out the actual DOMDocument to observers
730 }
731
732 // Called after we send an openURL:... down to WebCore.
733 - (void)opened
734 {
735     if ([self loadType] == FrameLoadTypeStandard && [[[self dataSource] _documentLoader] isClientRedirect])
736         [client _updateHistoryAfterClientRedirect];
737
738     if ([[self dataSource] _loadingFromPageCache]) {
739         // Force a layout to update view size and thereby update scrollbars.
740         NSView <WebDocumentView> *view = [[client frameView] documentView];
741         if ([view isKindOfClass:[WebHTMLView class]])
742             [(WebHTMLView *)view setNeedsToApplyStyles:YES];
743         [view setNeedsLayout: YES];
744         [view layout];
745
746         NSArray *responses = [[self documentLoader] responses];
747         NSURLResponse *response;
748         int i, count = [responses count];
749         for (i = 0; i < count; i++) {
750             response = [responses objectAtIndex: i];
751             // FIXME: If the WebKit client changes or cancels the request, this is not respected.
752             NSError *error;
753             id identifier;
754             NSURLRequest *request = [[NSURLRequest alloc] initWithURL:[response URL]];
755             [self requestFromDelegateForRequest:request identifier:&identifier error:&error];
756             [self sendRemainingDelegateMessagesWithIdentifier:identifier response:response length:(unsigned)[response expectedContentLength] error:error];
757             [request release];
758         }
759         
760         [client _loadedFromPageCache];
761
762         [[self documentLoader] setPrimaryLoadComplete:YES];
763
764         // FIXME: Why only this frame and not parent frames?
765         [self checkLoadCompleteForThisFrame];
766     }
767 }
768
769 - (void)commitProvisionalLoad:(NSDictionary *)pageCache
770 {
771     bool reload = loadType == FrameLoadTypeReload || loadType == FrameLoadTypeReloadAllowingStaleData;
772     
773     WebDataSource *provisionalDataSource = [[self provisionalDataSource] retain];
774     NSURLResponse *response = [provisionalDataSource response];
775     
776     NSDictionary *headers = [response isKindOfClass:[NSHTTPURLResponse class]]
777         ? [(NSHTTPURLResponse *)response allHeaderFields] : nil;
778     
779     if (loadType != FrameLoadTypeReplace)
780         [self closeOldDataSources];
781     
782     if (!pageCache)
783         [provisionalDataSource _makeRepresentation];
784     
785     [self transitionToCommitted:pageCache];
786     
787     // Call -_clientRedirectCancelledOrFinished: here so that the frame load delegate is notified that the redirect's
788     // status has changed, if there was a redirect.  The frame load delegate may have saved some state about
789     // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:.  Since we are
790     // just about to commit a new page, there cannot possibly be a pending redirect at this point.
791     if (sentRedirectNotification)
792         [self clientRedirectCancelledOrFinished:NO];
793     
794     NSURL *baseURL = [[provisionalDataSource request] _webDataRequestBaseURL];        
795     NSURL *URL = baseURL ? baseURL : [response URL];
796     
797     if (!URL || [URL _web_isEmpty])
798         URL = [NSURL URLWithString:@"about:blank"];    
799     
800     [[client _bridge] openURL:URL
801                      reload:reload 
802                 contentType:[response MIMEType]
803                     refresh:[headers objectForKey:@"Refresh"]
804                lastModified:(pageCache ? nil : wkGetNSURLResponseLastModifiedDate(response))
805                   pageCache:pageCache];
806     
807     [self opened];
808     
809     [provisionalDataSource release];
810 }
811
812 - (NSURLRequest *)initialRequest
813 {
814     return [[self activeDataSource] initialRequest];
815 }
816
817 - (void)_receivedData:(NSData *)data
818 {
819     [[self activeDocumentLoader] receivedData:data];
820 }
821
822 - (void)_setRequest:(NSURLRequest *)request
823 {
824     [[self activeDocumentLoader] setRequest:request];
825 }
826
827 - (void)_downloadWithLoadingConnection:(NSURLConnection *)connection
828     request:(NSURLRequest *)request response:(NSURLResponse *)response proxy:(id)proxy
829 {
830     [client _downloadWithLoadingConnection:connection request:request response:response proxy:proxy];
831 }
832
833 - (WebFrameBridge *)bridge
834 {
835     return [client _bridge];
836 }
837
838 - (void)_handleFallbackContent
839 {
840     [[self bridge] handleFallbackContent];
841 }
842
843 - (BOOL)_isStopping
844 {
845     return [[self activeDocumentLoader] isStopping];
846 }
847
848 - (void)_setupForReplaceByMIMEType:(NSString *)newMIMEType
849 {
850     [[self activeDocumentLoader] setupForReplaceByMIMEType:newMIMEType];
851 }
852
853 - (void)_setResponse:(NSURLResponse *)response
854 {
855     [[self activeDocumentLoader] setResponse:response];
856 }
857
858 - (void)_mainReceivedError:(NSError *)error complete:(BOOL)isComplete
859 {
860     [[self activeDocumentLoader] mainReceivedError:error complete:isComplete];
861 }
862
863 - (void)_finishedLoading
864 {
865     WebDataSource *ds = [self activeDataSource];
866     
867     WebFrameBridge *bridge = [self bridge];
868
869     [bridge retain];
870     [[self activeDocumentLoader] finishedLoading];
871
872     if ([ds _mainDocumentError] || ![ds webFrame]) {
873         [bridge release];
874         return;
875     }
876
877     [[self activeDocumentLoader] setPrimaryLoadComplete:YES];
878     if ([WebScriptDebugServer listenerCount])
879         [[WebScriptDebugServer sharedScriptDebugServer] webView:[client webView] didLoadMainResourceForDataSource:[self activeDataSource]];
880     [self checkLoadComplete];
881
882     [bridge release];
883 }
884
885 - (void)_notifyIconChanged:(NSURL *)iconURL
886 {
887     ASSERT([[WebIconDatabase sharedIconDatabase] _isEnabled]);
888     ASSERT(client == [[client webView] mainFrame]);
889
890     [[client webView] _willChangeValueForKey:_WebMainFrameIconKey];
891     
892     NSImage *icon = [[WebIconDatabase sharedIconDatabase] iconForURL:[[[self activeDataSource] _URL] _web_originalDataAsString] withSize:WebIconSmallSize];
893     
894     [client _dispatchDidReceiveIcon:icon];
895     
896     [[client webView] _didChangeValueForKey:_WebMainFrameIconKey];
897 }
898
899 - (NSURL *)_URL
900 {
901     return [[self activeDataSource] _URL];
902 }
903
904 - (NSError *)cancelledErrorWithRequest:(NSURLRequest *)request
905 {
906     return [NSError _webKitErrorWithDomain:NSURLErrorDomain
907                                       code:NSURLErrorCancelled
908                                        URL:[request URL]];
909 }
910
911 - (NSError *)fileDoesNotExistErrorWithResponse:(NSURLResponse *)response
912 {
913     return [NSError _webKitErrorWithDomain:NSURLErrorDomain
914                                                 code:NSURLErrorFileDoesNotExist
915                                                  URL:[response URL]];    
916 }
917
918 - (void)clearArchivedResources
919 {
920     [pendingArchivedResources removeAllObjects];
921     [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(deliverArchivedResources) object:nil];
922 }
923
924 - (void)deliverArchivedResources
925 {
926     if (![pendingArchivedResources count] || [self defersCallbacks])
927         return;
928         
929     NSEnumerator *keyEnum = [pendingArchivedResources keyEnumerator];
930     WebLoader *loader;
931     while ((loader = [keyEnum nextObject])) {
932         WebResource *resource = [pendingArchivedResources objectForKey:loader];
933         [loader didReceiveResponse:[resource _response]];
934         NSData *data = [resource data];
935         [loader didReceiveData:data lengthReceived:[data length] allAtOnce:YES];
936         [loader didFinishLoading];
937     }
938     
939     [pendingArchivedResources removeAllObjects];
940 }
941
942 - (void)deliverArchivedResourcesAfterDelay
943 {
944     if (![pendingArchivedResources count] || [self defersCallbacks])
945         return;
946     
947     [self performSelector:@selector(deliverArchivedResources) withObject:nil afterDelay:0];
948 }
949
950 static BOOL isCaseInsensitiveEqual(NSString *a, NSString *b)
951 {
952     return [a caseInsensitiveCompare:b] == NSOrderedSame;
953 }
954
955 // The following 2 methods are copied from [NSHTTPURLProtocol _cachedResponsePassesValidityChecks] and modified for our needs.
956 // FIXME: It would be nice to eventually to share this code somehow.
957 - (BOOL)_canUseResourceForRequest:(NSURLRequest *)theRequest
958 {
959     NSURLRequestCachePolicy policy = [theRequest cachePolicy];
960     
961     if (policy == NSURLRequestReturnCacheDataElseLoad) {
962         return YES;
963     } else if (policy == NSURLRequestReturnCacheDataDontLoad) {
964         return YES;
965     } else if (policy == NSURLRequestReloadIgnoringCacheData) {
966         return NO;
967     } else if ([theRequest valueForHTTPHeaderField:@"must-revalidate"] != nil) {
968         return NO;
969     } else if ([theRequest valueForHTTPHeaderField:@"proxy-revalidate"] != nil) {
970         return NO;
971     } else if ([theRequest valueForHTTPHeaderField:@"If-Modified-Since"] != nil) {
972         return NO;
973     } else if ([theRequest valueForHTTPHeaderField:@"Cache-Control"] != nil) {
974         return NO;
975     } else if (isCaseInsensitiveEqual(@"POST", [theRequest HTTPMethod])) {
976         return NO;
977     } else {
978         return YES;
979     }
980 }
981
982 - (BOOL)_canUseResourceWithResponse:(NSURLResponse *)response
983 {
984     if (wkGetNSURLResponseMustRevalidate(response))
985         return NO;
986     if (wkGetNSURLResponseCalculatedExpiration(response) - CFAbsoluteTimeGetCurrent() < 1)
987         return NO;
988     return YES;
989 }
990
991 - (NSMutableDictionary *)pendingArchivedResources
992 {
993     if (!pendingArchivedResources)
994         pendingArchivedResources = [[NSMutableDictionary alloc] init];
995     
996     return pendingArchivedResources;
997 }
998
999 - (BOOL)willUseArchiveForRequest:(NSURLRequest *)r originalURL:(NSURL *)originalURL loader:(WebLoader *)loader
1000 {
1001     if ([[r URL] isEqual:originalURL] && [self _canUseResourceForRequest:r]) {
1002         WebResource *resource = [[self activeDataSource] _archivedSubresourceForURL:originalURL];
1003         if (resource && [self _canUseResourceWithResponse:[resource _response]]) {
1004             CFDictionarySetValue((CFMutableDictionaryRef)[self pendingArchivedResources], loader, resource);
1005             // Deliver the resource after a delay because callers don't expect to receive callbacks while calling this method.
1006             [self deliverArchivedResourcesAfterDelay];
1007             return YES;
1008         }
1009     }
1010     return NO;
1011 }
1012
1013 - (BOOL)archiveLoadPendingForLoader:(WebLoader *)loader
1014 {
1015     return [pendingArchivedResources objectForKey:loader] != nil;
1016 }
1017
1018 - (void)cancelPendingArchiveLoadForLoader:(WebLoader *)loader
1019 {
1020     [pendingArchivedResources removeObjectForKey:loader];
1021     
1022     if (![pendingArchivedResources count])
1023         [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(deliverArchivedResources) object:nil];
1024 }
1025
1026 - (void)cannotShowMIMETypeForURL:(NSURL *)URL
1027 {
1028     [self handleUnimplementablePolicyWithErrorCode:WebKitErrorCannotShowMIMEType forURL:URL];    
1029 }
1030
1031 - (NSError *)interruptForPolicyChangeErrorWithRequest:(NSURLRequest *)request
1032 {
1033     return [NSError _webKitErrorWithDomain:WebKitErrorDomain code:WebKitErrorFrameLoadInterruptedByPolicyChange URL:[request URL]];
1034 }
1035
1036 - (BOOL)isHostedByObjectElement
1037 {
1038     // Handle <object> fallback for error cases.            
1039     DOMHTMLElement *hostElement = [client frameElement];
1040     return hostElement && [hostElement isKindOfClass:[DOMHTMLObjectElement class]];
1041 }
1042
1043 - (BOOL)isLoadingMainFrame
1044 {
1045     return [client _isMainFrame];
1046 }
1047
1048 + (BOOL)_canShowMIMEType:(NSString *)MIMEType
1049 {
1050     return [WebView canShowMIMEType:MIMEType];
1051 }
1052
1053 + (BOOL)_representationExistsForURLScheme:(NSString *)URLScheme
1054 {
1055     return [WebView _representationExistsForURLScheme:URLScheme];
1056 }
1057
1058 + (NSString *)_generatedMIMETypeForURLScheme:(NSString *)URLScheme
1059 {
1060     return [WebView _generatedMIMETypeForURLScheme:URLScheme];
1061 }
1062
1063 - (void)_checkNavigationPolicyForRequest:(NSURLRequest *)newRequest andCall:(id)obj withSelector:(SEL)sel
1064 {
1065     [self checkNavigationPolicyForRequest:newRequest
1066                               dataSource:[self activeDataSource]
1067                                 formState:nil
1068                                   andCall:obj
1069                              withSelector:sel];
1070 }
1071
1072 - (void)_checkContentPolicyForMIMEType:(NSString *)MIMEType andCall:(id)obj withSelector:(SEL)sel
1073 {
1074     WebPolicyDecisionListener *l = [[WebPolicyDecisionListener alloc] _initWithTarget:obj action:sel];
1075     listener = l;
1076     
1077     [l retain];
1078
1079     [client _dispatchDecidePolicyForMIMEType:MIMEType request:[[self activeDocumentLoader] request] decisionListener:listener];
1080
1081     [l release];
1082 }
1083
1084 - (void)cancelContentPolicy
1085 {
1086     [listener _invalidate];
1087     [listener release];
1088     listener = nil;
1089 }
1090
1091 BOOL isBackForwardLoadType(FrameLoadType type)
1092 {
1093     switch (type) {
1094         case FrameLoadTypeStandard:
1095         case FrameLoadTypeReload:
1096         case FrameLoadTypeReloadAllowingStaleData:
1097         case FrameLoadTypeSame:
1098         case FrameLoadTypeInternal:
1099         case FrameLoadTypeReplace:
1100             return false;
1101         case FrameLoadTypeBack:
1102         case FrameLoadTypeForward:
1103         case FrameLoadTypeIndexedBackForward:
1104             return true;
1105     }
1106     ASSERT_NOT_REACHED();
1107     return false;
1108 }
1109
1110 - (BOOL)shouldReloadToHandleUnreachableURLFromRequest:(NSURLRequest *)request
1111 {
1112     NSURL *unreachableURL = [request _webDataRequestUnreachableURL];
1113     if (unreachableURL == nil)
1114         return NO;
1115     
1116     if (!isBackForwardLoadType(policyLoadType))
1117         return NO;
1118     
1119     // We only treat unreachableURLs specially during the delegate callbacks
1120     // for provisional load errors and navigation policy decisions. The former
1121     // case handles well-formed URLs that can't be loaded, and the latter
1122     // case handles malformed URLs and unknown schemes. Loading alternate content
1123     // at other times behaves like a standard load.
1124     WebDataSource *compareDataSource = nil;
1125     if (delegateIsDecidingNavigationPolicy || delegateIsHandlingUnimplementablePolicy)
1126         compareDataSource = [self policyDataSource];
1127     else if (delegateIsHandlingProvisionalLoadError)
1128         compareDataSource = [self provisionalDataSource];
1129     
1130     return compareDataSource != nil && [unreachableURL isEqual:[[compareDataSource request] URL]];
1131 }
1132
1133 - (void)_loadRequest:(NSURLRequest *)request archive:(WebArchive *)archive
1134 {
1135     FrameLoadType type;
1136     
1137     ASSERT(!policyDocumentLoader);
1138     policyDocumentLoader = [client _createDocumentLoaderWithRequest:request];
1139     WebDataSource *newDataSource = [client _dataSourceForDocumentLoader:policyDocumentLoader];
1140
1141     NSMutableURLRequest *r = [newDataSource request];
1142     [self addExtraFieldsToRequest:r mainResource:YES alwaysFromRequest:NO];
1143     if ([client _shouldTreatURLAsSameAsCurrent:[request URL]]) {
1144         [r setCachePolicy:NSURLRequestReloadIgnoringCacheData];
1145         type = FrameLoadTypeSame;
1146     } else
1147         type = FrameLoadTypeStandard;
1148     
1149     [policyDocumentLoader setOverrideEncoding:[[self documentLoader] overrideEncoding]];
1150     [newDataSource _addToUnarchiveState:archive];
1151     
1152     // When we loading alternate content for an unreachable URL that we're
1153     // visiting in the b/f list, we treat it as a reload so the b/f list 
1154     // is appropriately maintained.
1155     if ([self shouldReloadToHandleUnreachableURLFromRequest:request]) {
1156         ASSERT(type == FrameLoadTypeStandard);
1157         type = FrameLoadTypeReload;
1158     }
1159     
1160     [self loadDataSource:newDataSource withLoadType:type formState:nil];
1161 }
1162
1163 - (void)_loadRequest:(NSURLRequest *)request triggeringAction:(NSDictionary *)action loadType:(FrameLoadType)type formState:(WebFormState *)formState
1164 {
1165     ASSERT(!policyDocumentLoader);
1166     policyDocumentLoader = [client _createDocumentLoaderWithRequest:request];
1167     WebDataSource *newDataSource = [client _dataSourceForDocumentLoader:policyDocumentLoader];
1168
1169     [policyDocumentLoader setTriggeringAction:action];
1170     [policyDocumentLoader setOverrideEncoding:[[self documentLoader] overrideEncoding]];
1171
1172     [self loadDataSource:newDataSource withLoadType:type formState:formState];
1173 }
1174
1175 - (void)_reloadAllowingStaleDataWithOverrideEncoding:(NSString *)encoding
1176 {
1177     WebDataSource *ds = [self dataSource];
1178     if (ds == nil)
1179         return;
1180
1181     NSMutableURLRequest *request = [[ds request] mutableCopy];
1182     NSURL *unreachableURL = [ds unreachableURL];
1183     if (unreachableURL != nil)
1184         [request setURL:unreachableURL];
1185
1186     [request setCachePolicy:NSURLRequestReturnCacheDataElseLoad];
1187     ASSERT(!policyDocumentLoader);
1188     policyDocumentLoader = [client _createDocumentLoaderWithRequest:request];
1189     WebDataSource *newDataSource = [client _dataSourceForDocumentLoader:policyDocumentLoader];
1190     [request release];
1191     
1192     [policyDocumentLoader setOverrideEncoding:encoding];
1193
1194     [self loadDataSource:newDataSource withLoadType:FrameLoadTypeReloadAllowingStaleData formState:nil];
1195 }
1196
1197 - (void)reload
1198 {
1199     WebDataSource *ds = [self dataSource];
1200     if (ds == nil)
1201         return;
1202
1203     NSMutableURLRequest *initialRequest = [ds request];
1204     
1205     // If a window is created by javascript, its main frame can have an empty but non-nil URL.
1206     // Reloading in this case will lose the current contents (see 4151001).
1207     if ([[[[ds request] URL] absoluteString] length] == 0)
1208         return;
1209
1210     // Replace error-page URL with the URL we were trying to reach.
1211     NSURL *unreachableURL = [initialRequest _webDataRequestUnreachableURL];
1212     if (unreachableURL != nil)
1213         initialRequest = [NSURLRequest requestWithURL:unreachableURL];
1214     
1215     ASSERT(!policyDocumentLoader);
1216     policyDocumentLoader = [client _createDocumentLoaderWithRequest:initialRequest];
1217     WebDataSource *newDataSource = [client _dataSourceForDocumentLoader:policyDocumentLoader];
1218     NSMutableURLRequest *request = [newDataSource request];
1219
1220     [request setCachePolicy:NSURLRequestReloadIgnoringCacheData];
1221
1222     // If we're about to rePOST, set up action so the app can warn the user
1223     if ([[request HTTPMethod] compare:@"POST" options:(NSCaseInsensitiveSearch | NSLiteralSearch)] == NSOrderedSame) {
1224         NSDictionary *action = [self actionInformationForNavigationType:WebNavigationTypeFormResubmitted
1225             event:nil originalURL:[request URL]];
1226         [policyDocumentLoader setTriggeringAction:action];
1227     }
1228
1229     [policyDocumentLoader setOverrideEncoding:[[ds _documentLoader] overrideEncoding]];
1230     
1231     [self loadDataSource:newDataSource withLoadType:FrameLoadTypeReload formState:nil];
1232 }
1233
1234 - (void)didReceiveServerRedirectForProvisionalLoadForFrame
1235 {
1236     [client _dispatchDidReceiveServerRedirectForProvisionalLoadForFrame];
1237 }
1238
1239 - (void)finishedLoadingDocument:(WebDocumentLoader *)loader
1240 {
1241     [[client _dataSourceForDocumentLoader:loader] _finishedLoading];
1242 }
1243
1244 - (void)committedLoadWithDocumentLoader:(WebDocumentLoader *)loader data:(NSData *)data
1245 {
1246     [[client _dataSourceForDocumentLoader:loader] _receivedData:data];
1247 }
1248
1249 - (BOOL)isReplacing
1250 {
1251     return loadType == FrameLoadTypeReplace;
1252 }
1253
1254 - (void)setReplacing
1255 {
1256     loadType = FrameLoadTypeReplace;
1257 }
1258
1259 - (void)revertToProvisionalWithDocumentLoader:(WebDocumentLoader *)loader
1260 {
1261     [[client _dataSourceForDocumentLoader:loader] _revertToProvisionalState];
1262 }
1263
1264 - (void)documentLoader:(WebDocumentLoader *)loader setMainDocumentError:(NSError *)error
1265 {
1266     [[client _dataSourceForDocumentLoader:loader] _setMainDocumentError:error];
1267 }
1268
1269 - (void)documentLoader:(WebDocumentLoader *)loader mainReceivedCompleteError:(NSError *)error
1270 {
1271     [loader setPrimaryLoadComplete:YES];
1272     if ([WebScriptDebugServer listenerCount])
1273         [[WebScriptDebugServer sharedScriptDebugServer] webView:[client webView] didLoadMainResourceForDataSource:[self activeDataSource]];
1274     [self checkLoadComplete];
1275 }
1276
1277 - (void)finalSetupForReplaceWithDocumentLoader:(WebDocumentLoader *)loader
1278 {
1279     [[client _dataSourceForDocumentLoader:loader] _clearUnarchivingState];
1280 }
1281
1282 - (void)prepareForLoadStart
1283 {
1284     [[client webView] _progressStarted:client];
1285     [[client webView] _didStartProvisionalLoadForFrame:client];
1286     [client _dispatchDidStartProvisionalLoadForFrame];
1287 }
1288
1289 - (BOOL)subframeIsLoading
1290 {
1291     // It's most likely that the last added frame is the last to load so we walk backwards.
1292     for (WebFrame *frame = [client _lastChildFrame]; frame; frame = [frame _previousSiblingFrame])
1293         if ([[frame dataSource] isLoading] || [[frame provisionalDataSource] isLoading])
1294             return YES;
1295     return NO;
1296 }
1297
1298 - (void)willChangeTitleForDocument:(WebDocumentLoader *)loader
1299 {
1300     // FIXME: should do this only in main frame case, right?
1301     [[client webView] _willChangeValueForKey:_WebMainFrameTitleKey];
1302 }
1303
1304 - (void)didChangeTitleForDocument:(WebDocumentLoader *)loader
1305 {
1306     // FIXME: should do this only in main frame case, right?
1307     [[client webView] _didChangeValueForKey:_WebMainFrameTitleKey];
1308
1309     // The title doesn't get communicated to the WebView until we are committed.
1310     if ([loader isCommitted]) {
1311         NSURL *URLForHistory = [[client _dataSourceForDocumentLoader:loader] _URLForHistory];
1312         if (URLForHistory != nil) {
1313             // Must update the entries in the back-forward list too.
1314             // This must go through the WebFrame because it has the right notion of the current b/f item.
1315             [client _setTitle:[loader title] forURL:URLForHistory];
1316             [[client webView] setMainFrameDocumentReady:YES]; // update observers with new DOMDocument
1317
1318             [client _dispatchDidReceiveTitle:[loader title]];
1319         }
1320     }
1321 }
1322
1323 - (FrameLoadType)loadType
1324 {
1325     return loadType;
1326 }
1327
1328 - (void)setLoadType:(FrameLoadType)type
1329 {
1330     loadType = type;
1331 }
1332
1333 - (void)invalidatePendingPolicyDecisionCallingDefaultAction:(BOOL)call
1334 {
1335     [listener _invalidate];
1336     [listener release];
1337     listener = nil;
1338
1339     NSURLRequest *request = policyRequest;
1340     NSString *frameName = policyFrameName;
1341     id target = policyTarget;
1342     SEL selector = policySelector;
1343     WebFormState *formState = policyFormState;
1344
1345     policyRequest = nil;
1346     policyFrameName = nil;
1347     policyTarget = nil;
1348     policySelector = nil;
1349     policyFormState = nil;
1350
1351     if (call) {
1352         if (frameName)
1353             objc_msgSend(target, selector, nil, nil, nil);
1354         else
1355             objc_msgSend(target, selector, nil, nil);
1356     }
1357
1358     [request release];
1359     [frameName release];
1360     [target release];
1361     [formState release];
1362 }
1363
1364 - (void)checkNewWindowPolicyForRequest:(NSURLRequest *)request action:(NSDictionary *)action frameName:(NSString *)frameName formState:(WebFormState *)formState andCall:(id)target withSelector:(SEL)selector
1365 {
1366     WebPolicyDecisionListener *decisionListener = [[WebPolicyDecisionListener alloc]
1367         _initWithTarget:self action:@selector(continueAfterNewWindowPolicy:)];
1368
1369     policyRequest = [request retain];
1370     policyTarget = [target retain];
1371     policyFrameName = [frameName retain];
1372     policySelector = selector;
1373     listener = [decisionListener retain];
1374     policyFormState = [formState retain];
1375
1376     [client _dispatchDecidePolicyForNewWindowAction:action request:request newFrameName:frameName decisionListener:decisionListener];
1377     
1378     [decisionListener release];
1379 }
1380
1381 - (void)continueAfterNewWindowPolicy:(WebPolicyAction)policy
1382 {
1383     NSURLRequest *request = [[policyRequest retain] autorelease];
1384     NSString *frameName = [[policyFrameName retain] autorelease];
1385     id target = [[policyTarget retain] autorelease];
1386     SEL selector = policySelector;
1387     WebFormState *formState = [[policyFormState retain] autorelease];
1388
1389     // will release policy* objects, hence the above retains
1390     [self invalidatePendingPolicyDecisionCallingDefaultAction:NO];
1391
1392     BOOL shouldContinue = NO;
1393
1394     switch (policy) {
1395     case WebPolicyIgnore:
1396         break;
1397     case WebPolicyDownload:
1398         // FIXME: should download full request
1399         [[client webView] _downloadURL:[request URL]];
1400         break;
1401     case WebPolicyUse:
1402         shouldContinue = YES;
1403         break;
1404     default:
1405         ASSERT_NOT_REACHED();
1406     }
1407
1408     objc_msgSend(target, selector, shouldContinue ? request : nil, frameName, formState);
1409 }
1410
1411 - (void)checkNavigationPolicyForRequest:(NSURLRequest *)request
1412                              dataSource:(WebDataSource *)dataSource
1413                               formState:(WebFormState *)formState
1414                                 andCall:(id)target
1415                            withSelector:(SEL)selector
1416 {
1417     NSDictionary *action = [[dataSource _documentLoader] triggeringAction];
1418     if (action == nil) {
1419         action = [self actionInformationForNavigationType:WebNavigationTypeOther
1420             event:nil originalURL:[request URL]];
1421         [[dataSource _documentLoader]  setTriggeringAction:action];
1422     }
1423         
1424     // Don't ask more than once for the same request or if we are loading an empty URL.
1425     // This avoids confusion on the part of the client.
1426     if ([request isEqual:[[dataSource _documentLoader] lastCheckedRequest]] || [[request URL] _web_isEmpty]) {
1427         [target performSelector:selector withObject:request withObject:nil];
1428         return;
1429     }
1430     
1431     // We are always willing to show alternate content for unreachable URLs;
1432     // treat it like a reload so it maintains the right state for b/f list.
1433     if ([request _webDataRequestUnreachableURL] != nil) {
1434         if (isBackForwardLoadType(policyLoadType))
1435             policyLoadType = FrameLoadTypeReload;
1436         [target performSelector:selector withObject:request withObject:nil];
1437         return;
1438     }
1439     
1440     [[dataSource _documentLoader] setLastCheckedRequest:request];
1441
1442     WebPolicyDecisionListener *decisionListener = [[WebPolicyDecisionListener alloc] _initWithTarget:self action:@selector(continueAfterNavigationPolicy:)];
1443     
1444     ASSERT(policyRequest == nil);
1445     policyRequest = [request retain];
1446     ASSERT(policyTarget == nil);
1447     policyTarget = [target retain];
1448     policySelector = selector;
1449     ASSERT(listener == nil);
1450     listener = [decisionListener retain];
1451     ASSERT(policyFormState == nil);
1452     policyFormState = [formState retain];
1453
1454     delegateIsDecidingNavigationPolicy = YES;
1455     [client _dispatchDecidePolicyForNavigationAction:action request:request decisionListener:decisionListener];
1456     delegateIsDecidingNavigationPolicy = NO;
1457     
1458     [decisionListener release];
1459 }
1460
1461 - (void)continueAfterNavigationPolicy:(WebPolicyAction)policy
1462 {
1463     NSURLRequest *request = [[policyRequest retain] autorelease];
1464     id target = [[policyTarget retain] autorelease];
1465     SEL selector = policySelector;
1466     WebFormState *formState = [[policyFormState retain] autorelease];
1467     
1468     // will release policy* objects, hence the above retains
1469     [self invalidatePendingPolicyDecisionCallingDefaultAction:NO];
1470
1471     BOOL shouldContinue = NO;
1472
1473     switch (policy) {
1474     case WebPolicyIgnore:
1475         break;
1476     case WebPolicyDownload:
1477         // FIXME: should download full request
1478         [[client webView] _downloadURL:[request URL]];
1479         break;
1480     case WebPolicyUse:
1481         if (![WebView _canHandleRequest:request]) {
1482             [self handleUnimplementablePolicyWithErrorCode:WebKitErrorCannotShowURL forURL:[request URL]];
1483         } else {
1484             shouldContinue = YES;
1485         }
1486         break;
1487     default:
1488         ASSERT_NOT_REACHED();
1489     }
1490
1491     [target performSelector:selector withObject:(shouldContinue ? request : nil) withObject:formState];
1492 }
1493
1494 // Called after the FormsDelegate is done processing willSubmitForm:
1495 - (void)continueAfterWillSubmitForm:(WebPolicyAction)policy
1496 {
1497     if (listener) {
1498         [listener _invalidate];
1499         [listener release];
1500         listener = nil;
1501     }
1502     [self startLoading];
1503 }
1504
1505 - (void)continueLoadRequestAfterNavigationPolicy:(NSURLRequest *)request formState:(WebFormState *)formState
1506 {
1507     // If we loaded an alternate page to replace an unreachableURL, we'll get in here with a
1508     // nil policyDataSource because loading the alternate page will have passed
1509     // through this method already, nested; otherwise, policyDataSource should still be set.
1510     ASSERT([self policyDataSource] || [[self provisionalDataSource] unreachableURL] != nil);
1511
1512     BOOL isTargetItem = [client _provisionalItemIsTarget];
1513
1514     // Two reasons we can't continue:
1515     //    1) Navigation policy delegate said we can't so request is nil. A primary case of this 
1516     //       is the user responding Cancel to the form repost nag sheet.
1517     //    2) User responded Cancel to an alert popped up by the before unload event handler.
1518     // The "before unload" event handler runs only for the main frame.
1519     BOOL canContinue = request && ([[client webView] mainFrame] != client || [[self bridge] shouldClose]);
1520
1521     if (!canContinue) {
1522         // If we were waiting for a quick redirect, but the policy delegate decided to ignore it, then we 
1523         // need to report that the client redirect was cancelled.
1524         if (quickRedirectComing)
1525             [self clientRedirectCancelledOrFinished:NO];
1526
1527         [self setPolicyDocumentLoader:nil];
1528
1529         // If the navigation request came from the back/forward menu, and we punt on it, we have the 
1530         // problem that we have optimistically moved the b/f cursor already, so move it back.  For sanity, 
1531         // we only do this when punting a navigation for the target frame or top-level frame.  
1532         if ((isTargetItem || [[client webView] mainFrame] == client) && isBackForwardLoadType(policyLoadType))
1533             [(WebFrame <WebFrameLoaderClient> *)[[client webView] mainFrame] _resetBackForwardList];
1534
1535         return;
1536     }
1537     
1538     FrameLoadType type = policyLoadType;
1539     WebDataSource *dataSource = [[self policyDataSource] retain];
1540     
1541     [self stopLoading];
1542     loadType = type;
1543
1544     [self startProvisionalLoad:dataSource];
1545
1546     [dataSource release];
1547     [self setPolicyDocumentLoader:nil];
1548     
1549     if (client == [[client webView] mainFrame])
1550         LOG(DocumentLoad, "loading %@", [[[self provisionalDataSource] request] URL]);
1551
1552     if (isBackForwardLoadType(type)) {
1553         if ([client _loadProvisionalItemFromPageCache])
1554             return;
1555     }
1556
1557     if (formState) {
1558         // It's a bit of a hack to reuse the WebPolicyDecisionListener for the continuation
1559         // mechanism across the willSubmitForm callout.
1560         listener = [[WebPolicyDecisionListener alloc] _initWithTarget:self action:@selector(continueAfterWillSubmitForm:)];
1561         [[[client webView] _formDelegate] frame:client sourceFrame:[formState sourceFrame] willSubmitForm:[formState form] withValues:[formState values] submissionListener:listener];
1562     } 
1563     else {
1564         [self continueAfterWillSubmitForm:WebPolicyUse];
1565     }
1566 }
1567
1568 - (void)loadDataSource:(WebDataSource *)newDataSource withLoadType:(FrameLoadType)type formState:(WebFormState *)formState
1569 {
1570     ASSERT([client webView] != nil);
1571
1572     // Unfortunately the view must be non-nil, this is ultimately due
1573     // to parser requiring a FrameView.  We should fix this dependency.
1574
1575     ASSERT([client frameView] != nil);
1576
1577     policyLoadType = type;
1578
1579     WebDocumentLoaderMac *loader = (WebDocumentLoaderMac *)[newDataSource _documentLoader];
1580
1581     WebFrame *parentFrame = [client parentFrame];
1582     if (parentFrame)
1583         [loader setOverrideEncoding:[[[parentFrame dataSource] _documentLoader] overrideEncoding]];
1584
1585     [loader setFrameLoader:self];
1586     [loader setDataSource:newDataSource];
1587
1588     [self invalidatePendingPolicyDecisionCallingDefaultAction:YES];
1589
1590     [self setPolicyDocumentLoader:loader];
1591
1592     [self checkNavigationPolicyForRequest:[newDataSource request]
1593                                dataSource:newDataSource
1594                                 formState:formState
1595                                   andCall:self
1596                              withSelector:@selector(continueLoadRequestAfterNavigationPolicy:formState:)];
1597 }
1598
1599 - (void)handleUnimplementablePolicyWithErrorCode:(int)code forURL:(NSURL *)URL
1600 {
1601     NSError *error = [NSError _webKitErrorWithDomain:WebKitErrorDomain code:code URL:URL];
1602     delegateIsHandlingUnimplementablePolicy = YES;
1603     [client _dispatchUnableToImplementPolicyWithError:error];
1604     delegateIsHandlingUnimplementablePolicy = NO;
1605 }
1606
1607 - (void)didFirstLayout
1608 {
1609     if ([[client webView] backForwardList]) {
1610         if (isBackForwardLoadType(loadType))
1611             [client _restoreScrollPositionAndViewState];
1612     }
1613
1614     firstLayoutDone = YES;
1615     [client _dispatchDidFirstLayoutInFrame];
1616 }
1617
1618 - (void)frameLoadCompleted
1619 {
1620     [client _frameLoadCompleted];
1621
1622     // After a canceled provisional load, firstLayoutDone is NO. Reset it to YES if we're displaying a page.
1623     if ([self dataSource])
1624         firstLayoutDone = YES;
1625 }
1626
1627 - (BOOL)firstLayoutDone
1628 {
1629     return firstLayoutDone;
1630 }
1631
1632 - (BOOL)isQuickRedirectComing
1633 {
1634     return quickRedirectComing;
1635 }
1636
1637 - (void)transitionToCommitted:(NSDictionary *)pageCache
1638 {
1639     ASSERT([client webView] != nil);
1640     
1641     switch ([self state]) {
1642         case WebFrameStateProvisional:
1643             goto keepGoing;
1644         
1645         case WebFrameStateCommittedPage:
1646         case WebFrameStateComplete:
1647             break;
1648     }
1649
1650     ASSERT_NOT_REACHED();
1651     return;
1652
1653 keepGoing:
1654
1655     [[[[client frameView] _scrollView] contentView] setCopiesOnScroll:YES];
1656
1657     [client _updateHistoryForCommit];
1658
1659     // The call to closeURL invokes the unload event handler, which can execute arbitrary
1660     // JavaScript. If the script initiates a new load, we need to abandon the current load,
1661     // or the two will stomp each other.
1662     WebDataSource *pd = [self provisionalDataSource];
1663     [[client _bridge] closeURL];
1664     if (pd != [self provisionalDataSource])
1665         return;
1666
1667     [self commitProvisionalLoad];
1668
1669     // Handle adding the URL to the back/forward list.
1670     WebDataSource *ds = [self dataSource];
1671     NSString *ptitle = [ds pageTitle];
1672
1673     switch (loadType) {
1674     case WebFrameLoadTypeForward:
1675     case WebFrameLoadTypeBack:
1676     case WebFrameLoadTypeIndexedBackForward:
1677         if ([[client webView] backForwardList]) {
1678             [client _updateHistoryForBackForwardNavigation];
1679             
1680             // Create a document view for this document, or used the cached view.
1681             if (pageCache) {
1682                 NSView <WebDocumentView> *cachedView = [pageCache objectForKey:WebPageCacheDocumentViewKey];
1683                 ASSERT(cachedView != nil);
1684                 [[client frameView] _setDocumentView:cachedView];
1685             } else
1686                 [client _makeDocumentView];
1687         }
1688         break;
1689
1690     case WebFrameLoadTypeReload:
1691     case WebFrameLoadTypeSame:
1692     case WebFrameLoadTypeReplace:
1693         [client _updateHistoryForReload];
1694         [client _makeDocumentView];
1695         break;
1696
1697     // FIXME - just get rid of this case, and merge WebFrameLoadTypeReloadAllowingStaleData with the above case
1698     case WebFrameLoadTypeReloadAllowingStaleData:
1699         [client _makeDocumentView];
1700         break;
1701
1702     case WebFrameLoadTypeStandard:
1703         [client _updateHistoryForStandardLoad];
1704         [client _makeDocumentView];
1705         break;
1706
1707     case WebFrameLoadTypeInternal:
1708         [client _updateHistoryForInternalLoad];
1709         [client _makeDocumentView];
1710         break;
1711
1712     // FIXME Remove this check when dummy ds is removed (whatever "dummy ds" is).
1713     // An exception should be thrown if we're in the WebFrameLoadTypeUninitialized state.
1714     default:
1715         ASSERT_NOT_REACHED();
1716     }
1717
1718     // Tell the client we've committed this URL.
1719     ASSERT([[client frameView] documentView] != nil);
1720     [[client webView] _didCommitLoadForFrame:client];
1721     [client _dispatchDidCommitLoadForFrame];
1722     
1723     // If we have a title let the WebView know about it.
1724     if (ptitle)
1725         [client _dispatchDidReceiveTitle:ptitle];
1726 }
1727
1728 - (void)checkLoadCompleteForThisFrame
1729 {
1730     ASSERT([client webView] != nil);
1731
1732     switch ([self state]) {
1733         case WebFrameStateProvisional: {
1734             if (delegateIsHandlingProvisionalLoadError)
1735                 return;
1736
1737             WebDataSource *pd = [[self provisionalDataSource] retain];
1738
1739             LOG(Loading, "%@:  checking complete in WebFrameStateProvisional", [client name]);
1740             // If we've received any errors we may be stuck in the provisional state and actually complete.
1741             NSError *error = [pd _mainDocumentError];
1742             if (error != nil) {
1743                 // Check all children first.
1744                 LOG(Loading, "%@:  checking complete, current state WebFrameStateProvisional", [client name]);
1745                 LoadErrorResetToken *resetToken = [client _tokenForLoadErrorReset];
1746                 BOOL shouldReset = YES;
1747                 if (![pd isLoading]) {
1748                     LOG(Loading, "%@:  checking complete in WebFrameStateProvisional, load done", [client name]);
1749                     [[client webView] _didFailProvisionalLoadWithError:error forFrame:client];
1750                     delegateIsHandlingProvisionalLoadError = YES;
1751                     [client _dispatchDidFailProvisionalLoadWithError:error];
1752
1753                     delegateIsHandlingProvisionalLoadError = NO;
1754                     [[client _internalLoadDelegate] webFrame:client didFinishLoadWithError:error];
1755
1756                     // FIXME: can stopping loading here possibly have
1757                     // any effect, if isLoading is false, which it
1758                     // must be, to be in this branch of the if? And is it ok to just do 
1759                     // a full-on stopLoading?
1760                     [self stopLoadingSubframes];
1761                     [[pd _documentLoader] stopLoading];
1762
1763                     // Finish resetting the load state, but only if another load hasn't been started by the
1764                     // delegate callback.
1765                     if (pd == [self provisionalDataSource])
1766                         [self clearProvisionalLoad];
1767                     else {
1768                         NSURL *unreachableURL = [[self provisionalDataSource] unreachableURL];
1769                         if (unreachableURL != nil && [unreachableURL isEqual:[[pd request] URL]])
1770                             shouldReset = NO;
1771                     }
1772                 }
1773                 if (shouldReset)
1774                     [client _resetAfterLoadError:resetToken];
1775                 else
1776                     [client _doNotResetAfterLoadError:resetToken];
1777             }
1778             [pd release];
1779             return;
1780         }
1781         
1782         case WebFrameStateCommittedPage: {
1783             WebDataSource *ds = [self dataSource];
1784             
1785             if (![ds isLoading]) {
1786                 WebFrameView *thisView = [client frameView];
1787                 NSView <WebDocumentView> *thisDocumentView = [thisView documentView];
1788                 ASSERT(thisDocumentView != nil);
1789
1790                 [self markLoadComplete];
1791
1792                 // FIXME: Is this subsequent work important if we already navigated away?
1793                 // Maybe there are bugs because of that, or extra work we can skip because
1794                 // the new page is ready.
1795
1796                 // Tell the just loaded document to layout.  This may be necessary
1797                 // for non-html content that needs a layout message.
1798                 if (!([[self dataSource] _isDocumentHTML])) {
1799                     [thisDocumentView setNeedsLayout:YES];
1800                     [thisDocumentView layout];
1801                     [thisDocumentView setNeedsDisplay:YES];
1802                 }
1803                  
1804                 // If the user had a scroll point scroll to it.  This will override
1805                 // the anchor point.  After much discussion it was decided by folks
1806                 // that the user scroll point should override the anchor point.
1807                 if ([[client webView] backForwardList]) {
1808                     switch ([self loadType]) {
1809                     case WebFrameLoadTypeForward:
1810                     case WebFrameLoadTypeBack:
1811                     case WebFrameLoadTypeIndexedBackForward:
1812                     case WebFrameLoadTypeReload:
1813                         [client _restoreScrollPositionAndViewState];
1814                         break;
1815
1816                     case WebFrameLoadTypeStandard:
1817                     case WebFrameLoadTypeInternal:
1818                     case WebFrameLoadTypeReloadAllowingStaleData:
1819                     case WebFrameLoadTypeSame:
1820                     case WebFrameLoadTypeReplace:
1821                         // Do nothing.
1822                         break;
1823
1824                     default:
1825                         ASSERT_NOT_REACHED();
1826                         break;
1827                     }
1828                 }
1829
1830                 NSError *error = [ds _mainDocumentError];
1831                 if (error != nil) {
1832                     [[client webView] _didFailLoadWithError:error forFrame:client];
1833                     [client _dispatchDidFailLoadWithError:error];
1834                     [[client _internalLoadDelegate] webFrame:client didFinishLoadWithError:error];
1835                 } else {
1836                     [[client webView] _didFinishLoadForFrame:client];
1837                     [client _dispatchDidFinishLoadForFrame];
1838                     [[client _internalLoadDelegate] webFrame:client didFinishLoadWithError:nil];
1839                 }
1840                 
1841                 [[client webView] _progressCompleted:client];
1842  
1843                 return;
1844             }
1845             return;
1846         }
1847         
1848         case WebFrameStateComplete:
1849             LOG(Loading, "%@:  checking complete, current state WebFrameStateComplete", [client name]);
1850             // Even if already complete, we might have set a previous item on a frame that
1851             // didn't do any data loading on the past transaction. Make sure to clear these out.
1852             [client _frameLoadCompleted];
1853             return;
1854     }
1855
1856     ASSERT_NOT_REACHED();
1857 }
1858
1859 - (void)continueLoadRequestAfterNewWindowPolicy:(NSURLRequest *)request frameName:(NSString *)frameName formState:(WebFormState *)formState
1860 {
1861     if (!request)
1862         return;
1863
1864     WebFrameBridge *bridge = [self bridge];
1865     [bridge retain];
1866
1867     WebFrame *mainFrame = [client _dispatchCreateWebViewWithRequest:nil];
1868     if (!mainFrame)
1869         goto exit;
1870
1871     WebFrameBridge *mainBridge = [mainFrame _bridge];
1872     [mainBridge retain];
1873
1874     [mainBridge setName:frameName];
1875
1876     [mainFrame _dispatchShow];
1877
1878     [mainBridge setOpener:bridge];
1879     [[mainFrame _frameLoader] _loadRequest:request triggeringAction:nil loadType:WebFrameLoadTypeStandard formState:formState];
1880
1881     [mainBridge release];
1882
1883 exit:
1884     [bridge release];
1885 }
1886
1887 - (void)sendRemainingDelegateMessagesWithIdentifier:(id)identifier response:(NSURLResponse *)response length:(unsigned)length error:(NSError *)error 
1888 {    
1889     if (response != nil)
1890         [client _dispatchResource:identifier didReceiveResponse:response fromDocumentLoader:documentLoader];
1891     
1892     if (length > 0)
1893         [client _dispatchResource:identifier didReceiveContentLength:(WebNSUInteger)length fromDocumentLoader:documentLoader];
1894     
1895     if (error == nil)
1896         [client _dispatchResource:identifier didFinishLoadingFromDocumentLoader:documentLoader];
1897     else
1898         [client _dispatchResource:identifier didFailLoadingWithError:error fromDocumentLoader:documentLoader];
1899 }
1900
1901 - (NSURLRequest *)requestFromDelegateForRequest:(NSURLRequest *)request identifier:(id *)identifier error:(NSError **)error
1902 {
1903     ASSERT(request != nil);
1904     
1905     *identifier = [client _dispatchIdentifierForInitialRequest:request fromDocumentLoader:documentLoader]; 
1906     NSURLRequest *newRequest = [client _dispatchResource:*identifier willSendRequest:request redirectResponse:nil fromDocumentLoader:documentLoader];
1907     
1908     if (newRequest == nil)
1909         *error = [NSError _webKitErrorWithDomain:NSURLErrorDomain code:NSURLErrorCancelled URL:[request URL]];
1910     else
1911         *error = nil;
1912     
1913     return newRequest;
1914 }
1915
1916 - (void)loadRequest:(NSURLRequest *)request inFrameNamed:(NSString *)frameName
1917 {
1918     if (frameName == nil) {
1919         [client loadRequest:request];
1920         return;
1921     }
1922
1923     WebFrame *frame = [client findFrameNamed:frameName];
1924     if (frame != nil) {
1925         [frame loadRequest:request];
1926         return;
1927     }
1928
1929     NSDictionary *action = [self actionInformationForNavigationType:WebNavigationTypeOther
1930         event:nil originalURL:[request URL]];
1931     [self checkNewWindowPolicyForRequest:request action:action frameName:frameName formState:nil
1932         andCall:self withSelector:@selector(continueLoadRequestAfterNewWindowPolicy:frameName:formState:)];
1933 }
1934
1935 - (void)postWithURL:(NSURL *)URL referrer:(NSString *)referrer target:(NSString *)target
1936     data:(NSArray *)postData contentType:(NSString *)contentType
1937     triggeringEvent:(NSEvent *)event form:(DOMElement *)form formValues:(NSDictionary *)values
1938 {
1939     // When posting, use the NSURLRequestReloadIgnoringCacheData load flag.
1940     // This prevents a potential bug which may cause a page with a form that uses itself
1941     // as an action to be returned from the cache without submitting.
1942
1943     // FIXME: Where's the code that implements what the comment above says?
1944
1945     NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:URL];
1946     [self addExtraFieldsToRequest:request mainResource:YES alwaysFromRequest:YES];
1947     [request _web_setHTTPReferrer:referrer];
1948     [request setHTTPMethod:@"POST"];
1949     webSetHTTPBody(request, postData);
1950     [request _web_setHTTPContentType:contentType];
1951
1952     NSDictionary *action = [self actionInformationForLoadType:FrameLoadTypeStandard isFormSubmission:YES event:event originalURL:URL];
1953     WebFormState *formState = nil;
1954     if (form && values)
1955         formState = [[WebFormState alloc] initWithForm:form values:values sourceFrame:client];
1956
1957     if (target != nil) {
1958         WebFrame *targetFrame = [client findFrameNamed:target];
1959         if (targetFrame != nil)
1960             [[targetFrame _frameLoader] _loadRequest:request triggeringAction:action loadType:FrameLoadTypeStandard formState:formState];
1961         else
1962             [self checkNewWindowPolicyForRequest:request action:action frameName:target formState:formState
1963                 andCall:self withSelector:@selector(continueLoadRequestAfterNewWindowPolicy:frameName:formState:)];
1964     } else
1965         [self _loadRequest:request triggeringAction:action loadType:FrameLoadTypeStandard formState:formState];
1966
1967     [request release];
1968     [formState release];
1969 }
1970
1971 - (void)detachChildren
1972 {
1973     // FIXME: is it really necessary to do this in reverse order any more?
1974     WebFrame *child = [client _lastChildFrame];
1975     WebFrame *prev = [child _previousSiblingFrame];
1976     for (; child; child = prev, prev = [child _previousSiblingFrame])
1977         [[child _frameLoader] detachFromParent];
1978 }
1979
1980 - (void)detachFromParent
1981 {
1982     WebFrameBridge *bridge = [[self bridge] retain];
1983
1984     [bridge closeURL];
1985     [self stopLoading];
1986     [client _detachedFromParent1];
1987     [self detachChildren];
1988     [client _detachedFromParent2];
1989     [self setDocumentLoader:nil];
1990     [client _detachedFromParent3];
1991     [[[client parentFrame] _bridge] removeChild:bridge];
1992
1993     NSObject <WebFrameLoaderClient>* c = [client retain];
1994     [bridge close];
1995     [c _detachedFromParent4];
1996     [c release];
1997
1998     [bridge release];
1999 }
2000
2001 - (void)addExtraFieldsToRequest:(NSMutableURLRequest *)request mainResource:(BOOL)mainResource alwaysFromRequest:(BOOL)f
2002 {
2003     [request _web_setHTTPUserAgent:[[client webView] userAgentForURL:[request URL]]];
2004     
2005     if ([self loadType] == FrameLoadTypeReload)
2006         [request setValue:@"max-age=0" forHTTPHeaderField:@"Cache-Control"];
2007     
2008     // Don't set the cookie policy URL if it's already been set.
2009     if ([request mainDocumentURL] == nil) {
2010         if (mainResource && (client == [[client webView] mainFrame] || f))
2011             [request setMainDocumentURL:[request URL]];
2012         else
2013             [request setMainDocumentURL:[[[[client webView] mainFrame] dataSource] _URL]];
2014     }
2015     
2016     if (mainResource)
2017         [request setValue:@"text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5" forHTTPHeaderField:@"Accept"];
2018 }
2019
2020 - (void)safeLoadURL:(NSURL *)URL
2021 {
2022    // Call the bridge because this is where our security checks are made.
2023     [[self bridge] loadURL:URL 
2024                   referrer:[[[[self dataSource] request] URL] _web_originalDataAsString]
2025                     reload:NO
2026                userGesture:YES       
2027                     target:nil
2028            triggeringEvent:[NSApp currentEvent]
2029                       form:nil 
2030                 formValues:nil];
2031 }
2032
2033 - (NSDictionary *)actionInformationForLoadType:(FrameLoadType)type isFormSubmission:(BOOL)isFormSubmission event:(NSEvent *)event originalURL:(NSURL *)URL
2034 {
2035     WebNavigationType navType;
2036     if (isFormSubmission) {
2037         navType = WebNavigationTypeFormSubmitted;
2038     } else if (event == nil) {
2039         if (type == FrameLoadTypeReload)
2040             navType = WebNavigationTypeReload;
2041         else if (isBackForwardLoadType(type))
2042             navType = WebNavigationTypeBackForward;
2043         else
2044             navType = WebNavigationTypeOther;
2045     } else {
2046         navType = WebNavigationTypeLinkClicked;
2047     }
2048     return [self actionInformationForNavigationType:navType event:event originalURL:URL];
2049 }
2050
2051 - (NSDictionary *)actionInformationForNavigationType:(NavigationType)navigationType event:(NSEvent *)event originalURL:(NSURL *)URL
2052 {
2053     switch ([event type]) {
2054         case NSLeftMouseDown:
2055         case NSRightMouseDown:
2056         case NSOtherMouseDown:
2057         case NSLeftMouseUp:
2058         case NSRightMouseUp:
2059         case NSOtherMouseUp: {
2060             NSView *topViewInEventWindow = [[event window] contentView];
2061             NSView *viewContainingPoint = [topViewInEventWindow hitTest:[topViewInEventWindow convertPoint:[event locationInWindow] fromView:nil]];
2062             while (viewContainingPoint != nil) {
2063                 if ([viewContainingPoint isKindOfClass:[WebView class]])
2064                     break;
2065                 viewContainingPoint = [viewContainingPoint superview];
2066             }
2067             if (viewContainingPoint != nil) {
2068                 NSPoint point = [viewContainingPoint convertPoint:[event locationInWindow] fromView:nil];
2069                 NSDictionary *elementInfo = [(WebView *)viewContainingPoint elementAtPoint:point];
2070                 return [NSDictionary dictionaryWithObjectsAndKeys:
2071                     [NSNumber numberWithInt:navigationType], WebActionNavigationTypeKey,
2072                     elementInfo, WebActionElementKey,
2073                     [NSNumber numberWithInt:[event buttonNumber]], WebActionButtonKey,
2074                     [NSNumber numberWithInt:[event modifierFlags]], WebActionModifierFlagsKey,
2075                     URL, WebActionOriginalURLKey,
2076                     nil];
2077             }
2078         }
2079             
2080         // fall through
2081         
2082         default:
2083             return [NSDictionary dictionaryWithObjectsAndKeys:
2084                 [NSNumber numberWithInt:navigationType], WebActionNavigationTypeKey,
2085                 [NSNumber numberWithInt:[event modifierFlags]], WebActionModifierFlagsKey,
2086                 URL, WebActionOriginalURLKey,
2087                 nil];
2088     }
2089 }
2090
2091 // Called every time a resource is completely loaded, or an error is received.
2092 - (void)checkLoadComplete
2093 {
2094     ASSERT([client webView] != nil);
2095
2096     WebFrame *parent;
2097     for (WebFrame *frame = client; frame; frame = parent) {
2098         [frame retain];
2099         [[frame _frameLoader] checkLoadCompleteForThisFrame];
2100         parent = [frame parentFrame];
2101         [frame release];
2102     }
2103 }
2104
2105 @end