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