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