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