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