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