Reviewed by John Sullivan.
[WebKit-https.git] / WebKit / WebView / WebFrame.m
1 /*
2  * Copyright (C) 2005 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 <WebKit/WebFrameInternal.h>
30
31 #import <WebKit/DOM.h>
32 #import <WebKit/WebArchive.h>
33 #import <WebKit/WebBackForwardList.h>
34 #import <WebKit/WebFrameBridge.h>
35 #import <WebKit/WebDataProtocol.h>
36 #import <WebKit/WebDataSourcePrivate.h>
37 #import <WebKit/WebDefaultResourceLoadDelegate.h>
38 #import <WebKit/WebDefaultUIDelegate.h>
39 #import <WebKit/WebDocumentInternal.h>
40 #import <WebKit/WebFormDataStream.h>
41 #import <WebKit/WebFrameLoadDelegate.h>
42 #import <WebKit/WebFrameViewInternal.h>
43 #import <WebKit/WebHistoryPrivate.h>
44 #import <WebKit/WebHistoryItemPrivate.h>
45 #import <WebKit/WebHTMLRepresentationPrivate.h>
46 #import <WebKit/WebHTMLViewInternal.h>
47 #import <WebKit/WebHTMLViewPrivate.h>
48 #import <WebKit/WebKitErrorsPrivate.h>
49 #import <WebKit/WebKitLogging.h>
50 #import <WebKit/WebKitNSStringExtras.h>
51 #import <WebKit/WebKitStatisticsPrivate.h>
52 #import <WebKit/WebNetscapePluginDocumentView.h>
53 #import <WebKit/WebNetscapePluginEmbeddedView.h>
54 #import <WebKit/WebNSObjectExtras.h>
55 #import <WebKit/WebNSURLExtras.h>
56 #import <WebKit/WebNSURLRequestExtras.h>
57 #import <WebKit/WebNullPluginView.h>
58 #import <WebKit/WebPreferencesPrivate.h>
59 #import <WebKit/WebPlugin.h>
60 #import <WebKit/WebPluginController.h>
61 #import <WebKit/WebPluginDocumentView.h>
62 #import <WebKit/WebResourceLoadDelegate.h>
63 #import <WebKit/WebResourcePrivate.h>
64 #import <WebKit/WebViewInternal.h>
65 #import <WebKit/WebUIDelegate.h>
66 #import <WebKit/WebScriptDebugDelegatePrivate.h>
67 #import <WebKitSystemInterface.h>
68
69 #import <objc/objc-runtime.h>
70
71 #ifndef NDEBUG
72 static const char * const stateNames[] = {
73     "WebFrameStateProvisional",
74     "WebFrameStateCommittedPage",
75     "WebFrameStateComplete"
76 };
77 #endif
78
79 /*
80 Here is the current behavior matrix for four types of navigations:
81
82 Standard Nav:
83
84  Restore form state:   YES
85  Restore scroll and focus state:  YES
86  WF Cache policy: NSURLRequestUseProtocolCachePolicy
87  Add to back/forward list: YES
88  
89 Back/Forward:
90
91  Restore form state:   YES
92  Restore scroll and focus state:  YES
93  WF Cache policy: NSURLRequestReturnCacheDataElseLoad
94  Add to back/forward list: NO
95
96 Reload (meaning only the reload button):
97
98  Restore form state:   NO
99  Restore scroll and focus state:  YES
100  WF Cache policy: NSURLRequestReloadIgnoringCacheData
101  Add to back/forward list: NO
102
103 Repeat load of the same URL (by any other means of navigation other than the reload button, including hitting return in the location field):
104
105  Restore form state:   NO
106  Restore scroll and focus state:  NO, reset to initial conditions
107  WF Cache policy: NSURLRequestReloadIgnoringCacheData
108  Add to back/forward list: NO
109 */
110
111 NSString *WebPageCacheEntryDateKey = @"WebPageCacheEntryDateKey";
112 NSString *WebPageCacheDataSourceKey = @"WebPageCacheDataSourceKey";
113 NSString *WebPageCacheDocumentViewKey = @"WebPageCacheDocumentViewKey";
114
115 @interface NSObject (WebExtraPerformMethod)
116
117 - (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2 withObject:(id)object3;
118
119 @end
120
121 @implementation NSObject (WebExtraPerformMethod)
122
123 - (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2 withObject:(id)object3
124 {
125     return objc_msgSend(self, aSelector, object1, object2, object3);
126 }
127
128 @end
129
130 // One day we might want to expand the use of this kind of class such that we'd receive one
131 // over the bridge, and possibly hand it on through to the FormsDelegate.
132 // Today it is just used internally to keep some state as we make our way through a bunch
133 // layers while doing a load.
134 @interface WebFormState : NSObject
135 {
136     DOMElement *_form;
137     NSDictionary *_values;
138     WebFrame *_sourceFrame;
139 }
140 - (id)initWithForm:(DOMElement *)form values:(NSDictionary *)values sourceFrame:(WebFrame *)sourceFrame;
141 - (DOMElement *)form;
142 - (NSDictionary *)values;
143 - (WebFrame *)sourceFrame;
144 @end
145
146 @interface WebFrame (ForwardDecls)
147 - (void)_loadRequest:(NSURLRequest *)request triggeringAction:(NSDictionary *)action loadType:(WebFrameLoadType)loadType formState:(WebFormState *)formState;
148 - (void)_loadHTMLString:(NSString *)string baseURL:(NSURL *)URL unreachableURL:(NSURL *)unreachableURL;
149 - (NSDictionary *)_actionInformationForLoadType:(WebFrameLoadType)loadType isFormSubmission:(BOOL)isFormSubmission event:(NSEvent *)event originalURL:(NSURL *)URL;
150
151 - (void)_saveScrollPositionAndViewStateToItem:(WebHistoryItem *)item;
152 - (void)_restoreScrollPositionAndViewState;
153
154 - (WebHistoryItem *)_createItem: (BOOL)useOriginal;
155 - (WebHistoryItem *)_createItemTreeWithTargetFrame:(WebFrame *)targetFrame clippedAtTarget:(BOOL)doClip;
156 - (WebHistoryItem *)_currentBackForwardListItemToResetTo;
157 - (void)_stopLoadingSubframes;
158 @end
159
160 @interface WebFrame (FrameTraversal)
161 - (WebFrame *)_firstChildFrame;
162 - (WebFrame *)_lastChildFrame;
163 - (unsigned)_childFrameCount;
164 - (WebFrame *)_previousSiblingFrame;
165 - (WebFrame *)_nextSiblingFrame;
166 - (WebFrame *)_traverseNextFrameStayWithin:(WebFrame *)stayWithin;
167 @end
168
169 @interface WebFramePrivate : NSObject
170 {
171 @public
172     WebFrameView *webFrameView;
173     WebDataSource *dataSource;
174     WebDataSource *provisionalDataSource;
175     WebFrameBridge *bridge;
176     WebFrameState state;
177     WebFrameLoadType loadType;
178     WebHistoryItem *currentItem;        // BF item for our current content
179     WebHistoryItem *provisionalItem;    // BF item for where we're trying to go
180                                         // (only known when navigating to a pre-existing BF item)
181     WebHistoryItem *previousItem;       // BF item for previous content, see _itemForSavingDocState
182
183     WebPolicyDecisionListener *listener;
184     // state we'll need to continue after waiting for the policy delegate's decision
185     NSURLRequest *policyRequest;
186     NSString *policyFrameName;
187     id policyTarget;
188     SEL policySelector;
189     WebFormState *policyFormState;
190     WebDataSource *policyDataSource;
191     WebFrameLoadType policyLoadType;
192
193     BOOL quickRedirectComing;
194     BOOL sentRedirectNotification;
195     BOOL isStoppingLoad;
196     BOOL delegateIsHandlingProvisionalLoadError;
197     BOOL delegateIsDecidingNavigationPolicy;
198     BOOL delegateIsHandlingUnimplementablePolicy;
199     BOOL firstLayoutDone;
200     
201     id internalLoadDelegate;
202     WebScriptDebugger *scriptDebugger;
203
204     NSString *frameNamespace;
205 }
206
207 - (void)setWebFrameView:(WebFrameView *)v;
208 - (WebFrameView *)webFrameView;
209 - (void)setDataSource:(WebDataSource *)d;
210 - (WebDataSource *)dataSource;
211 - (void)setProvisionalDataSource:(WebDataSource *)d;
212 - (WebDataSource *)provisionalDataSource;
213 - (WebFrameLoadType)loadType;
214 - (void)setLoadType:(WebFrameLoadType)loadType;
215
216 - (void)setProvisionalItem:(WebHistoryItem *)item;
217 - (WebHistoryItem *)provisionalItem;
218 - (void)setPreviousItem:(WebHistoryItem *)item;
219 - (WebHistoryItem *)previousItem;
220 - (void)setCurrentItem:(WebHistoryItem *)item;
221 - (WebHistoryItem *)currentItem;
222
223 @end
224
225 @implementation WebFramePrivate
226
227 - init
228 {
229     self = [super init];
230     if (!self) {
231         return nil;
232     }
233     
234     state = WebFrameStateComplete;
235     loadType = WebFrameLoadTypeStandard;
236     
237     return self;
238 }
239
240 - (void)dealloc
241 {
242     [webFrameView release];
243     [dataSource release];
244     [provisionalDataSource release];
245
246     [currentItem release];
247     [provisionalItem release];
248     [previousItem release];
249     
250     [scriptDebugger release];
251     
252     ASSERT(listener == nil);
253     ASSERT(policyRequest == nil);
254     ASSERT(policyFrameName == nil);
255     ASSERT(policyTarget == nil);
256     ASSERT(policyFormState == nil);
257     ASSERT(policyDataSource == nil);
258     ASSERT(frameNamespace == nil);
259
260     [super dealloc];
261 }
262
263 - (WebFrameView *)webFrameView { return webFrameView; }
264 - (void)setWebFrameView: (WebFrameView *)v 
265
266     [v retain];
267     [webFrameView release];
268     webFrameView = v;
269 }
270
271 - (WebDataSource *)dataSource { return dataSource; }
272 - (void)setDataSource: (WebDataSource *)d
273 {
274     [d retain];
275     [dataSource release];
276     dataSource = d;
277 }
278
279 - (WebDataSource *)provisionalDataSource { return provisionalDataSource; }
280 - (void)setProvisionalDataSource: (WebDataSource *)d
281 {
282     ASSERT(!d || !provisionalDataSource);
283     [d retain];
284     [provisionalDataSource release];
285     provisionalDataSource = d;
286 }
287
288 - (WebFrameLoadType)loadType { return loadType; }
289 - (void)setLoadType: (WebFrameLoadType)t
290 {
291     loadType = t;
292 }
293
294 - (WebHistoryItem *)provisionalItem { return provisionalItem; }
295 - (void)setProvisionalItem: (WebHistoryItem *)item
296 {
297     [item retain];
298     [provisionalItem release];
299     provisionalItem = item;
300 }
301
302 - (WebHistoryItem *)previousItem { return previousItem; }
303 - (void)setPreviousItem:(WebHistoryItem *)item
304 {
305     [item retain];
306     [previousItem release];
307     previousItem = item;
308 }
309
310 - (WebHistoryItem *)currentItem { return currentItem; }
311 - (void)setCurrentItem:(WebHistoryItem *)item
312 {
313     [item retain];
314     [currentItem release];
315     currentItem = item;
316 }
317
318 @end
319
320 static inline WebFrame *Frame(WebCoreFrameBridge *bridge)
321 {
322     return [(WebFrameBridge *)bridge webFrame];
323 }
324
325 @implementation WebFrame (FrameTraversal)
326 - (WebFrame *)_firstChildFrame
327 {
328     return Frame([[self _bridge] firstChild]);
329 }
330
331 - (WebFrame *)_lastChildFrame
332 {
333     return Frame([[self _bridge] lastChild]);
334 }
335
336 - (unsigned)_childFrameCount
337 {
338     return [[self _bridge] childCount];
339 }
340
341 - (WebFrame *)_previousSiblingFrame;
342 {
343     return Frame([[self _bridge] previousSibling]);
344 }
345
346 - (WebFrame *)_nextSiblingFrame;
347 {
348     return Frame([[self _bridge] nextSibling]);
349 }
350
351 - (WebFrame *)_traverseNextFrameStayWithin:(WebFrame *)stayWithin
352 {
353     return Frame([[self _bridge] traverseNextFrameStayWithin:[stayWithin _bridge]]);
354 }
355
356 @end
357
358 @implementation WebFrame (WebPrivate)
359
360 - (NSURLRequest *)_webDataRequestForData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName: (NSString *)encodingName baseURL:(NSURL *)URL unreachableURL:(NSURL *)unreachableURL
361 {
362     NSURL *fakeURL = [NSURL _web_uniqueWebDataURL];
363     NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] initWithURL:fakeURL] autorelease];
364     [request _webDataRequestSetData:data];
365     [request _webDataRequestSetEncoding:encodingName];
366     [request _webDataRequestSetBaseURL:URL];
367     [request _webDataRequestSetUnreachableURL:unreachableURL];
368     [request _webDataRequestSetMIMEType: MIMEType ? MIMEType : (NSString *)@"text/html"];
369     return request;
370 }
371
372 - (BOOL)_shouldReloadToHandleUnreachableURLFromRequest:(NSURLRequest *)request
373 {
374     NSURL *unreachableURL = [request _webDataRequestUnreachableURL];
375     if (unreachableURL == nil) {
376         return NO;
377     }
378     
379     if (_private->policyLoadType != WebFrameLoadTypeForward
380         && _private->policyLoadType != WebFrameLoadTypeBack
381         && _private->policyLoadType != WebFrameLoadTypeIndexedBackForward) {
382         return NO;
383     }
384     
385     // We only treat unreachableURLs specially during the delegate callbacks
386     // for provisional load errors and navigation policy decisions. The former
387     // case handles well-formed URLs that can't be loaded, and the latter
388     // case handles malformed URLs and unknown schemes. Loading alternate content
389     // at other times behaves like a standard load.
390     WebDataSource *compareDataSource = nil;
391     if (_private->delegateIsDecidingNavigationPolicy || _private->delegateIsHandlingUnimplementablePolicy) {
392         compareDataSource = _private->policyDataSource;
393     } else if (_private->delegateIsHandlingProvisionalLoadError) {
394         compareDataSource = [self provisionalDataSource];
395     }
396     
397     return compareDataSource != nil && [unreachableURL isEqual:[[compareDataSource request] URL]];
398 }
399
400 - (void)_loadRequest:(NSURLRequest *)request subresources:(NSArray *)subresources subframeArchives:(NSArray *)subframeArchives
401 {
402     WebFrameLoadType loadType;
403     
404     // note this copies request
405     WebDataSource *newDataSource = [[WebDataSource alloc] initWithRequest:request];
406     NSMutableURLRequest *r = [newDataSource request];
407     [self _addExtraFieldsToRequest:r alwaysFromRequest: NO];
408     if ([self _shouldTreatURLAsSameAsCurrent:[request URL]]) {
409         [r setCachePolicy:NSURLRequestReloadIgnoringCacheData];
410         loadType = WebFrameLoadTypeSame;
411     } else {
412         loadType = WebFrameLoadTypeStandard;
413     }
414     
415     [newDataSource _setOverrideEncoding:[[self dataSource] _overrideEncoding]];
416     [newDataSource _addSubresources:subresources];
417     [newDataSource _addSubframeArchives:subframeArchives];
418     
419     // When we loading alternate content for an unreachable URL that we're
420     // visiting in the b/f list, we treat it as a reload so the b/f list 
421     // is appropriately maintained.
422     if ([self _shouldReloadToHandleUnreachableURLFromRequest:request]) {
423         ASSERT(loadType == WebFrameLoadTypeStandard);
424         loadType = WebFrameLoadTypeReload;
425     }
426     
427     [self _loadDataSource:newDataSource withLoadType:loadType formState:nil];
428     [newDataSource release];
429 }
430
431 // helper method used in various nav cases below
432 - (void)_addBackForwardItemClippedAtTarget:(BOOL)doClip
433 {
434     if ([[self dataSource] _URLForHistory] != nil) {
435         WebHistoryItem *bfItem = [[[self webView] mainFrame] _createItemTreeWithTargetFrame:self clippedAtTarget:doClip];
436         LOG (BackForward, "for frame %@, adding item  %@\n", [self name], bfItem);
437         [[[self webView] backForwardList] addItem:bfItem];
438     }
439 }
440
441 - (WebHistoryItem *)_createItem:(BOOL)useOriginal
442 {
443     WebDataSource *dataSrc = [self dataSource];
444     NSURLRequest *request;
445     NSURL *unreachableURL = [dataSrc unreachableURL];
446     NSURL *URL;
447     NSURL *originalURL;
448     WebHistoryItem *bfItem;
449
450     if (useOriginal) {
451         request = [dataSrc _originalRequest];
452     } else {
453         request = [dataSrc request];
454     }
455
456     if (unreachableURL != nil) {
457         URL = unreachableURL;
458         originalURL = unreachableURL;
459     } else {
460         URL = [request URL];
461         originalURL = [[dataSrc _originalRequest] URL];
462     }
463
464     LOG (History, "creating item for %@", request);
465     
466     // Frames that have never successfully loaded any content
467     // may have no URL at all. Currently our history code can't
468     // deal with such things, so we nip that in the bud here.
469     // Later we may want to learn to live with nil for URL.
470     // See bug 3368236 and related bugs for more information.
471     if (URL == nil) {
472         URL = [NSURL URLWithString:@"about:blank"];
473     }
474     if (originalURL == nil) {
475         originalURL = [NSURL URLWithString:@"about:blank"];
476     }
477     
478     bfItem = [[[WebHistoryItem alloc] initWithURL:URL target:[self name] parent:[[self parentFrame] name] title:[dataSrc pageTitle]] autorelease];
479     [bfItem setOriginalURLString:[originalURL _web_originalDataAsString]];
480
481     // save form state if this is a POST
482     [bfItem _setFormInfoFromRequest:request];
483
484     // Set the item for which we will save document state
485     [_private setPreviousItem:[_private currentItem]];
486     [_private setCurrentItem:bfItem];
487
488     return bfItem;
489 }
490
491 /*
492     In the case of saving state about a page with frames, we store a tree of items that mirrors the frame tree.  
493     The item that was the target of the user's navigation is designated as the "targetItem".  
494     When this method is called with doClip=YES we're able to create the whole tree except for the target's children, 
495     which will be loaded in the future.  That part of the tree will be filled out as the child loads are committed.
496 */
497 - (WebHistoryItem *)_createItemTreeWithTargetFrame:(WebFrame *)targetFrame clippedAtTarget:(BOOL)doClip
498 {
499     WebHistoryItem *bfItem = [self _createItem:[self parentFrame] ? YES : NO];
500
501     [self _saveScrollPositionAndViewStateToItem:[_private previousItem]];
502     if (!(doClip && self == targetFrame)) {
503         // save frame state for items that aren't loading (khtml doesn't save those)
504         [_private->bridge saveDocumentState];
505
506         for (WebFrame *child = [self _firstChildFrame]; child; child = [child _nextSiblingFrame])
507             [bfItem addChildItem:[child _createItemTreeWithTargetFrame:targetFrame clippedAtTarget:doClip]];
508     }
509     if (self == targetFrame)
510         [bfItem setIsTargetItem:YES];
511
512     return bfItem;
513 }
514
515 - (WebFrame *)_immediateChildFrameNamed:(NSString *)name
516 {
517     return Frame([[self _bridge] childFrameNamed:name]);
518 }
519
520 // FIXME: this exists only as a convenience for Safari, consider moving there
521 - (BOOL)_isDescendantOfFrame:(WebFrame *)ancestor
522 {
523     return [[self _bridge] isDescendantOfFrame:[ancestor _bridge]];
524 }
525
526 - (BOOL)_isFrameSet
527 {
528     return [_private->bridge isFrameSet];
529 }
530
531 - (void)_detachChildren
532 {
533     // FIXME: is it really necessary to do this in reverse order any more?
534     WebFrame *child = [self _lastChildFrame];
535     WebFrame *prev = [child _previousSiblingFrame];
536     for (; child; child = prev, prev = [child _previousSiblingFrame])
537         [child _detachFromParent];
538 }
539
540 - (void)_closeOldDataSources
541 {
542     // FIXME: is it important for this traversal to be postorder instead of preorder?
543     // FIXME: add helpers for postorder traversal?
544     for (WebFrame *child = [self _firstChildFrame]; child; child = [child _nextSiblingFrame])
545         [child _closeOldDataSources];
546
547     if (_private->dataSource)
548         [[[self webView] _frameLoadDelegateForwarder] webView:[self webView] willCloseFrame:self];
549 }
550
551 - (void)_detachFromParent
552 {
553     WebFrameBridge *bridge = _private->bridge;
554
555     [bridge closeURL];
556     [self stopLoading];
557
558     [self _saveScrollPositionAndViewStateToItem:[_private currentItem]];
559     [self _detachChildren];
560
561     [_private->webFrameView _setWebFrame:nil]; // needed for now to be compatible w/ old behavior
562
563     [self _setDataSource:nil];
564     [_private setWebFrameView:nil];
565
566     [self retain]; // retain self temporarily because dealloc can re-enter this method
567
568     [bridge close];
569     [[[self parentFrame] _bridge] removeChild:bridge];
570
571     _private->bridge = nil;
572
573     [self release];
574 }
575
576 - (void)_setDataSource:(WebDataSource *)ds
577 {
578     if (ds == nil && _private->dataSource == nil) {
579         return;
580     }
581
582     ASSERT(ds != _private->dataSource);
583
584     if (_private->dataSource) {
585         // Make sure that any work that is triggered by resigning first reponder can get done.
586         // The main example where this came up is the textDidEndEditing that is sent to the
587         // FormsDelegate (3223413).  We need to do this before _detachChildren, since that will
588         // remove the views as a side-effect of freeing the bridge, at which point we can't
589         // post the FormDelegate messages.
590         //
591         // Note that this can also take FirstResponder away from a child of our frameView that
592         // is not in a child frame's view.  This is OK because we are in the process
593         // of loading new content, which will blow away all editors in this top frame, and if
594         // a non-editor is firstReponder it will not be affected by endEditingFor:.
595         // Potentially one day someone could write a DocView whose editors were not all
596         // replaced by loading new content, but that does not apply currently.
597         NSView *frameView = [self frameView];
598         NSWindow *window = [frameView window];
599         NSResponder *firstResp = [window firstResponder];
600         if ([firstResp isKindOfClass:[NSView class]]
601             && [(NSView *)firstResp isDescendantOf:frameView])
602         {
603             [window endEditingFor:firstResp];
604         }
605
606         [self _detachChildren];
607
608         [_private->dataSource _setWebFrame:nil];
609     } else {
610         ASSERT(![self _childFrameCount]);
611     }
612
613     [_private setDataSource:ds];
614     [ds _setWebFrame:self];
615 }
616
617 - (void)_setLoadType: (WebFrameLoadType)t
618 {
619     [_private setLoadType:t];
620 }
621
622 - (WebFrameLoadType)_loadType
623 {
624     return [_private loadType];
625 }
626
627 - (void)_makeDocumentView
628 {
629     NSView <WebDocumentView> *documentView = [_private->webFrameView _makeDocumentViewForDataSource:_private->dataSource];
630     if (!documentView) {
631         return;
632     }
633
634     // FIXME: We could save work and not do this for a top-level view that is not a WebHTMLView.
635     WebFrameView *v = _private->webFrameView;
636     [_private->bridge createFrameViewWithNSView:documentView marginWidth:[v _marginWidth] marginHeight:[v _marginHeight]];
637     [self _updateDrawsBackground];
638     [_private->bridge installInFrame:[v _scrollView]];
639
640     // Call setDataSource on the document view after it has been placed in the view hierarchy.
641     // This what we for the top-level view, so should do this for views in subframes as well.
642     [documentView setDataSource:_private->dataSource];
643 }
644
645 - (void)_receivedMainResourceError:(NSError *)error
646 {
647     if ([self _state] == WebFrameStateProvisional) {
648         NSURL *failedURL = [[_private->provisionalDataSource _originalRequest] URL];
649         // When we are pre-commit, the currentItem is where the pageCache data resides
650         NSDictionary *pageCache = [[_private currentItem] pageCache];
651         [[self _bridge] didNotOpenURL:failedURL pageCache:pageCache];
652         // We're assuming that WebCore invalidates its pageCache state in didNotOpen:pageCache:
653         [[_private currentItem] setHasPageCache:NO];
654     }
655 }
656
657 - (void)_transitionToCommitted:(NSDictionary *)pageCache
658 {
659     ASSERT([self webView] != nil);
660     
661     switch ([self _state]) {
662         case WebFrameStateProvisional:
663         {
664             [[[[self frameView] _scrollView] contentView] setCopiesOnScroll:YES];
665
666             WebFrameLoadType loadType = [self _loadType];
667             if (loadType == WebFrameLoadTypeForward ||
668                 loadType == WebFrameLoadTypeBack ||
669                 loadType == WebFrameLoadTypeIndexedBackForward ||
670                 (loadType == WebFrameLoadTypeReload && [_private->provisionalDataSource unreachableURL] != nil))
671             {
672                 // Once committed, we want to use current item for saving DocState, and
673                 // the provisional item for restoring state.
674                 // Note previousItem must be set before we close the URL, which will
675                 // happen when the data source is made non-provisional below
676                 [_private setPreviousItem:[_private currentItem]];
677                 ASSERT([_private provisionalItem]);
678                 [_private setCurrentItem:[_private provisionalItem]];
679                 [_private setProvisionalItem:nil];
680             }
681
682             // The call to closeURL invokes the unload event handler, which can execute arbitrary
683             // JavaScript. If the script initiates a new load, we need to abandon the current load,
684             // or the two will stomp each other.
685             WebDataSource *pd = _private->provisionalDataSource;
686             [[self _bridge] closeURL];
687             if (pd != _private->provisionalDataSource)
688                 return;
689
690             // Set the committed data source on the frame.
691             [self _setDataSource:_private->provisionalDataSource];
692                 
693             [self _setProvisionalDataSource: nil];
694
695             [self _setState: WebFrameStateCommittedPage];
696         
697             // Handle adding the URL to the back/forward list.
698             WebDataSource *ds = [self dataSource];
699             NSString *ptitle = [ds pageTitle];
700
701             switch (loadType) {
702             case WebFrameLoadTypeForward:
703             case WebFrameLoadTypeBack:
704             case WebFrameLoadTypeIndexedBackForward:
705                 if ([[self webView] backForwardList]) {
706                     // Must grab the current scroll position before disturbing it
707                     [self _saveScrollPositionAndViewStateToItem:[_private previousItem]];
708                     
709                     // Create a document view for this document, or used the cached view.
710                     if (pageCache){
711                         NSView <WebDocumentView> *cachedView = [pageCache objectForKey: WebPageCacheDocumentViewKey];
712                         ASSERT(cachedView != nil);
713                         [[self frameView] _setDocumentView: cachedView];
714                     }
715                     else
716                         [self _makeDocumentView];
717                 }
718                 break;
719
720             case WebFrameLoadTypeReload:
721             case WebFrameLoadTypeSame:
722             case WebFrameLoadTypeReplace:
723             {
724                 WebHistoryItem *currItem = [_private currentItem];
725                 LOG(PageCache, "Clearing back/forward cache, %@\n", [currItem URL]);
726                 [currItem setHasPageCache:NO];
727                 if (loadType == WebFrameLoadTypeReload) {
728                     [self _saveScrollPositionAndViewStateToItem:currItem];
729                 }
730                 NSURLRequest *request = [ds request];
731                 if ([request _webDataRequestUnreachableURL] == nil) {
732                     // Sometimes loading a page again leads to a different result because of cookies.  Bugzilla 4072
733                     [currItem setURL:[request URL]];
734                 }
735                 // Update the last visited time.  Mostly interesting for URL autocompletion
736                 // statistics.
737                 NSURL *URL = [[[ds _originalRequest] URL] _webkit_canonicalize];
738                 WebHistory *sharedHistory = [WebHistory optionalSharedHistory];
739                 WebHistoryItem *oldItem = [sharedHistory itemForURL:URL];
740                 if (oldItem)
741                     [sharedHistory setLastVisitedTimeInterval:[NSDate timeIntervalSinceReferenceDate] forItem:oldItem];
742                 
743                 [self _makeDocumentView];
744                 break;
745             }
746
747             // FIXME - just get rid of this case, and merge WebFrameLoadTypeReloadAllowingStaleData with the above case
748             case WebFrameLoadTypeReloadAllowingStaleData:
749                 [self _makeDocumentView];
750                 break;
751                 
752             case WebFrameLoadTypeStandard:
753                 if (![ds _isClientRedirect]) {
754                     // Add item to history and BF list
755                     NSURL *URL = [ds _URLForHistory];
756                     if (URL && ![URL _web_isEmpty]){
757                         ASSERT([self webView]);
758                         if (![[[self webView] preferences] privateBrowsingEnabled]) {
759                             WebHistoryItem *entry = [[WebHistory optionalSharedHistory] addItemForURL:URL];
760                             if (ptitle)
761                                 [entry setTitle: ptitle];                            
762                         }
763                         [self _addBackForwardItemClippedAtTarget:YES];
764                     }
765
766                 } else {
767                     NSURLRequest *request = [ds request];
768                     
769                     // update the URL in the BF list that we made before the redirect, unless
770                     // this is alternate content for an unreachable URL (we want the BF list
771                     // item to remember the unreachable URL in case it becomes reachable later)
772                     if ([request _webDataRequestUnreachableURL] == nil) {
773                         [[_private currentItem] setURL:[request URL]];
774
775                         // clear out the form data so we don't repost it to the wrong place if we
776                         // ever go back/forward to this item
777                         [[_private currentItem] _setFormInfoFromRequest:request];
778
779                         // We must also clear out form data so we don't try to restore it into the incoming page,
780                         // see -_opened
781                     }
782                 }
783                 [self _makeDocumentView];
784                 break;
785                 
786             case WebFrameLoadTypeInternal:
787                 // Add an item to the item tree for this frame
788                 ASSERT(![ds _isClientRedirect]);
789                 WebFrame *parentFrame = [self parentFrame];
790                 if (parentFrame) {
791                     WebHistoryItem *parentItem = [parentFrame->_private currentItem];
792                     // The only case where parentItem==nil should be when a parent frame loaded an
793                     // empty URL, which doesn't set up a current item in that parent.
794                     if (parentItem)
795                         [parentItem addChildItem:[self _createItem: YES]];
796                 } else {
797                     // See 3556159.  It's not clear if it's valid to be in WebFrameLoadTypeOnLoadEvent
798                     // for a top-level frame, but that was a likely explanation for those crashes,
799                     // so let's guard against it.
800                     // ...and all WebFrameLoadTypeOnLoadEvent uses were folded to WebFrameLoadTypeInternal
801                     ERROR("no parent frame in _transitionToCommitted:, loadType=%d", loadType);
802                 }
803                 [self _makeDocumentView];
804                 break;
805
806             // FIXME Remove this check when dummy ds is removed.  An exception should be thrown
807             // if we're in the WebFrameLoadTypeUninitialized state.
808             default:
809                 ASSERT_NOT_REACHED();
810             }
811
812             
813             // Tell the client we've committed this URL.
814             ASSERT([[self frameView] documentView] != nil);
815             [[self webView] _didCommitLoadForFrame: self];
816             [[[self webView] _frameLoadDelegateForwarder] webView:[self webView] didCommitLoadForFrame:self];
817             
818             // If we have a title let the WebView know about it.
819             if (ptitle) {
820                 [[[self webView] _frameLoadDelegateForwarder] webView:[self webView]
821                                                            didReceiveTitle:ptitle
822                                                                   forFrame:self];
823             }
824             break;
825         }
826         
827         case WebFrameStateCommittedPage:
828         case WebFrameStateComplete:
829         default:
830         {
831             ASSERT_NOT_REACHED();
832         }
833     }
834 }
835
836 - (void)_commitProvisionalLoad:(NSDictionary *)pageCache
837 {
838     WebFrameLoadType loadType = [self _loadType];
839     bool reload = loadType == WebFrameLoadTypeReload || loadType == WebFrameLoadTypeReloadAllowingStaleData;
840     
841     WebDataSource *provisionalDataSource = [self provisionalDataSource];
842     NSURLResponse *response = [provisionalDataSource response];
843
844     NSDictionary *headers = [response isKindOfClass:[NSHTTPURLResponse class]]
845         ? [(NSHTTPURLResponse *)response allHeaderFields] : nil;
846     
847     if (loadType != WebFrameLoadTypeReplace)
848         [self _closeOldDataSources];
849     
850     if (!pageCache)
851         [provisionalDataSource _makeRepresentation];
852     
853     [self _transitionToCommitted:pageCache];
854
855     // Call -_clientRedirectCancelledOrFinished: here so that the frame load delegate is notified that the redirect's
856     // status has changed, if there was a redirect.  The frame load delegate may have saved some state about
857     // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:.  Since we are
858     // just about to commit a new page, there cannot possibly be a pending redirect at this point.
859     if (_private->sentRedirectNotification)
860         [self _clientRedirectCancelledOrFinished:NO];
861     
862     NSURL *baseURL = [[provisionalDataSource request] _webDataRequestBaseURL];        
863     NSURL *URL = baseURL ? baseURL : [response URL];
864
865     if (!URL || [URL _web_isEmpty])
866         URL = [NSURL URLWithString:@"about:blank"];    
867
868     [[self _bridge] openURL:URL
869                     reload:reload 
870                     contentType:[response MIMEType]
871                     refresh:[headers objectForKey:@"Refresh"]
872                     lastModified:(pageCache ? nil : WKGetNSURLResponseLastModifiedDate(response))
873                     pageCache:pageCache];
874     
875     [self _opened];
876 }
877
878 - (BOOL)_canCachePage
879 {
880     return [[[self webView] backForwardList] _usesPageCache];
881 }
882
883 - (void)_purgePageCache
884 {
885     // This method implements the rule for purging the page cache.
886     unsigned sizeLimit = [[[self webView] backForwardList] pageCacheSize];
887     unsigned pagesCached = 0;
888     WebBackForwardList *backForwardList = [[self webView] backForwardList];
889     NSArray *backList = [backForwardList backListWithLimit: 999999];
890     WebHistoryItem *oldestNonSnapbackItem = nil;
891     
892     unsigned i;
893     for (i = 0; i < [backList count]; i++){
894         WebHistoryItem *item = [backList objectAtIndex: i];
895         if ([item hasPageCache]){
896             if (oldestNonSnapbackItem == nil && ![item alwaysAttemptToUsePageCache])
897                 oldestNonSnapbackItem = item;
898             pagesCached++;
899         }
900     }
901
902     // Snapback items are never directly purged here.
903     if (pagesCached >= sizeLimit) {
904         LOG(PageCache, "Purging back/forward cache, %@\n", [oldestNonSnapbackItem URL]);
905         [oldestNonSnapbackItem setHasPageCache:NO];
906     }
907 }
908
909 - (WebFrameState)_state
910 {
911     return _private->state;
912 }
913
914 static CFAbsoluteTime _timeOfLastCompletedLoad;
915 + (CFAbsoluteTime)_timeOfLastCompletedLoad
916 {
917     return _timeOfLastCompletedLoad;
918 }
919
920 - (BOOL)_createPageCacheForItem:(WebHistoryItem *)item
921 {
922     NSMutableDictionary *pageCache;
923
924     [item setHasPageCache: YES];
925
926     if (![_private->bridge saveDocumentToPageCache]){
927         [item setHasPageCache: NO];
928         return NO;
929     }
930     else {
931         pageCache = [item pageCache];
932         [pageCache setObject:[NSDate date]  forKey: WebPageCacheEntryDateKey];
933         [pageCache setObject:[self dataSource] forKey: WebPageCacheDataSourceKey];
934         [pageCache setObject:[[self frameView] documentView] forKey: WebPageCacheDocumentViewKey];
935     }
936     return YES;
937 }
938
939 - (void)_setState: (WebFrameState)newState
940 {
941     LOG(Loading, "%@:  transition from %s to %s", [self name], stateNames[_private->state], stateNames[newState]);
942     if ([self webView])
943         LOG(Timing, "%@:  transition from %s to %s, %f seconds since start of document load", [self name], stateNames[_private->state], stateNames[newState], CFAbsoluteTimeGetCurrent() - [[[[self webView] mainFrame] dataSource] _loadingStartedTime]);
944     
945     if (newState == WebFrameStateComplete && self == [[self webView] mainFrame]){
946         LOG(DocumentLoad, "completed %@ (%f seconds)", [[[self dataSource] request] URL], CFAbsoluteTimeGetCurrent() - [[self dataSource] _loadingStartedTime]);
947     }
948     
949     _private->state = newState;
950     
951     if (_private->state == WebFrameStateProvisional) {
952         _private->firstLayoutDone = NO;
953         [_private->bridge provisionalLoadStarted];
954     
955         // FIXME: This is OK as long as no one resizes the window,
956         // but in the case where someone does, it means garbage outside
957         // the occupied part of the scroll view.
958         [[[self frameView] _scrollView] setDrawsBackground:NO];
959
960         // Cache the page, if possible.
961         // Don't write to the cache if in the middle of a redirect, since we will want to
962         // store the final page we end up on.
963         // No point writing to the cache on a reload or loadSame, since we will just write
964         // over it again when we leave that page.
965         WebHistoryItem *item = [_private currentItem];
966         WebFrameLoadType loadType = [self _loadType];
967         if ([self _canCachePage]
968             && [_private->bridge canCachePage]
969             && item
970             && !_private->quickRedirectComing
971             && loadType != WebFrameLoadTypeReload 
972             && loadType != WebFrameLoadTypeReloadAllowingStaleData
973             && loadType != WebFrameLoadTypeSame
974             && ![[self dataSource] isLoading]
975             && ![[self dataSource] _isStopping])
976         {
977             if ([[[self dataSource] representation] isKindOfClass: [WebHTMLRepresentation class]]) {
978                 if (![item pageCache]){
979
980                     // Add the items to this page's cache.
981                     if ([self _createPageCacheForItem:item]) {
982                         LOG(PageCache, "Saving page to back/forward cache, %@\n", [[self dataSource] _URL]);
983
984                         // See if any page caches need to be purged after the addition of this
985                         // new page cache.
986                         [self _purgePageCache];
987                     }
988                     else {
989                         LOG(PageCache, "NOT saving page to back/forward cache, unable to create items, %@\n", [[self dataSource] _URL]);
990                     }
991                 }
992             }
993             else {
994                 // Put the document into a null state, so it can be restored correctly.
995                 [_private->bridge clear];
996             }
997         }
998         else {
999             LOG(PageCache, "NOT saving page to back/forward cache, %@\n", [[self dataSource] _URL]);
1000         }
1001     }
1002     
1003     if (_private->state == WebFrameStateComplete) {
1004         NSScrollView *sv = [[self frameView] _scrollView];
1005         if ([[self webView] drawsBackground])
1006             [sv setDrawsBackground:YES];
1007         [_private setPreviousItem:nil];
1008         _timeOfLastCompletedLoad = CFAbsoluteTimeGetCurrent();
1009
1010         [[self dataSource] _stopRecordingResponses];
1011
1012         // After a canceled provisional load, firstLayoutDone is NO. Reset it to YES if we're displaying a page.
1013         if (_private->dataSource)
1014             _private->firstLayoutDone = YES;
1015     }
1016 }
1017
1018 // Called after we send an openURL:... down to WebCore.
1019 - (void)_opened
1020 {
1021     if ([self _loadType] == WebFrameLoadTypeStandard && [[self dataSource] _isClientRedirect]) {
1022         // Clear out form data so we don't try to restore it into the incoming page.  Must happen after
1023         // khtml has closed the URL and saved away the form state.
1024         WebHistoryItem *item = [_private currentItem];
1025         [item setDocumentState:nil];
1026         [item setScrollPoint:NSZeroPoint];
1027     }
1028
1029     if ([[self dataSource] _loadingFromPageCache]){
1030         // Force a layout to update view size and thereby update scrollbars.
1031         NSView <WebDocumentView> *view = [[self frameView] documentView];
1032         if ([view isKindOfClass:[WebHTMLView class]]) {
1033             [(WebHTMLView *)view setNeedsToApplyStyles:YES];
1034         }
1035         [view setNeedsLayout: YES];
1036         [view layout];
1037
1038         NSArray *responses = [[self dataSource] _responses];
1039         NSURLResponse *response;
1040         int i, count = [responses count];
1041         for (i = 0; i < count; i++){
1042             response = [responses objectAtIndex: i];
1043             // FIXME: If the WebKit client changes or cancels the request, this is not respected.
1044             NSError *error;
1045             id identifier;
1046             NSURLRequest *request = [[NSURLRequest alloc] initWithURL:[response URL]];
1047             [self _requestFromDelegateForRequest:request identifier:&identifier error:&error];
1048             [self _sendRemainingDelegateMessagesWithIdentifier:identifier response:response length:[response expectedContentLength] error:error];
1049             [request release];
1050         }
1051         
1052         // Release the resources kept in the page cache.  They will be
1053         // reset when we leave this page.  The core side of the page cache
1054         // will have already been invalidated by the bridge to prevent
1055         // premature release.
1056         [[_private currentItem] setHasPageCache: NO];
1057
1058         [[self dataSource] _setPrimaryLoadComplete: YES];
1059         // why only this frame and not parent frames?
1060         [self _checkLoadCompleteForThisFrame];
1061     }
1062 }
1063
1064 - (void)_checkLoadCompleteForThisFrame
1065 {
1066     ASSERT([self webView] != nil);
1067
1068     switch ([self _state]) {
1069         case WebFrameStateProvisional:
1070         {
1071             WebDataSource *pd = [self provisionalDataSource];
1072             
1073             LOG(Loading, "%@:  checking complete in WebFrameStateProvisional", [self name]);
1074             // If we've received any errors we may be stuck in the provisional state and actually
1075             // complete.
1076             NSError *error = [pd _mainDocumentError];
1077             if (error != nil) {
1078                 // Check all children first.
1079                 LOG(Loading, "%@:  checking complete, current state WebFrameStateProvisional", [self name]);
1080                 WebHistoryItem *resetItem = [self _currentBackForwardListItemToResetTo];
1081                 BOOL shouldReset = YES;
1082                 if (![pd isLoading]) {
1083                     LOG(Loading, "%@:  checking complete in WebFrameStateProvisional, load done", [self name]);
1084                     [[self webView] _didFailProvisionalLoadWithError:error forFrame:self];
1085                     _private->delegateIsHandlingProvisionalLoadError = YES;
1086                     [[[self webView] _frameLoadDelegateForwarder] webView:[self webView]
1087                                           didFailProvisionalLoadWithError:error
1088                                                                  forFrame:self];
1089                     _private->delegateIsHandlingProvisionalLoadError = NO;
1090                     [_private->internalLoadDelegate webFrame:self didFinishLoadWithError:error];
1091
1092                     // FIXME: can stopping loading here possibly have
1093                     // any effect, if isLoading is false, which it
1094                     // must be, to be in this branch of the if? And is it ok to just do 
1095                     // a full-on stopLoading?
1096                     [self _stopLoadingSubframes];
1097                     [pd _stopLoading];
1098
1099
1100                     // Finish resetting the load state, but only if another load hasn't been started by the
1101                     // delegate callback.
1102                     if (pd == _private->provisionalDataSource) {
1103                         [self _setProvisionalDataSource:nil];
1104                         
1105                         [[self webView] _progressCompleted:self];
1106                         
1107                         [self _setState:WebFrameStateComplete];
1108                     } else {
1109                         NSURL *unreachableURL = [_private->provisionalDataSource unreachableURL];
1110                         if (unreachableURL != nil && [unreachableURL isEqual:[[pd request] URL]]) {
1111                             shouldReset = NO;
1112                         }
1113                     }
1114                 }
1115                 if (shouldReset && resetItem != nil) {
1116                     [[[self webView] backForwardList] goToItem:resetItem];
1117                 }
1118             }
1119             return;
1120         }
1121         
1122         case WebFrameStateCommittedPage:
1123         {
1124             WebDataSource *ds = [self dataSource];
1125             
1126             //LOG(Loading, "%@:  checking complete, current state WEBFRAMESTATE_COMMITTED", [self name]);
1127             if (![ds isLoading]) {
1128                 WebFrameView *thisView = [self frameView];
1129                 NSView <WebDocumentView> *thisDocumentView = [thisView documentView];
1130                 ASSERT(thisDocumentView != nil);
1131
1132                 // FIXME: need to avoid doing this in the non-HTML case or the bridge may assert.
1133                 // Should instead make sure the bridge/part is in the proper state even for
1134                 // non-HTML content, or make a call to the document and let it deal with the bridge.
1135
1136                 [self _setState:WebFrameStateComplete];
1137
1138                 // FIXME: Is this subsequent work important if we already navigated away?
1139                 // Maybe there are bugs because of that, or extra work we can skip because
1140                 // the new page is ready.
1141
1142                 // Tell the just loaded document to layout.  This may be necessary
1143                 // for non-html content that needs a layout message.
1144                 if (!([[self dataSource] _isDocumentHTML])) {
1145                     [thisDocumentView setNeedsLayout:YES];
1146                     [thisDocumentView layout];
1147                     [thisDocumentView setNeedsDisplay:YES];
1148                 }
1149                  
1150                 // If the user had a scroll point scroll to it.  This will override
1151                 // the anchor point.  After much discussion it was decided by folks
1152                 // that the user scroll point should override the anchor point.
1153                 if ([[self webView] backForwardList]) {
1154                     switch ([self _loadType]) {
1155                     case WebFrameLoadTypeForward:
1156                     case WebFrameLoadTypeBack:
1157                     case WebFrameLoadTypeIndexedBackForward:
1158                     case WebFrameLoadTypeReload:
1159                         [self _restoreScrollPositionAndViewState];
1160                         break;
1161
1162                     case WebFrameLoadTypeStandard:
1163                     case WebFrameLoadTypeInternal:
1164                     case WebFrameLoadTypeReloadAllowingStaleData:
1165                     case WebFrameLoadTypeSame:
1166                     case WebFrameLoadTypeReplace:
1167                         // Do nothing.
1168                         break;
1169
1170                     default:
1171                         ASSERT_NOT_REACHED();
1172                         break;
1173                     }
1174                 }
1175
1176                 NSError *error = [ds _mainDocumentError];
1177                 if (error != nil) {
1178                     [[self webView] _didFailLoadWithError:error forFrame:self];
1179                     [[[self webView] _frameLoadDelegateForwarder] webView:[self webView]
1180                                                      didFailLoadWithError:error
1181                                                                  forFrame:self];
1182                     [_private->internalLoadDelegate webFrame:self didFinishLoadWithError:error];
1183                 } else {
1184                     [[self webView] _didFinishLoadForFrame:self];
1185                     [[[self webView] _frameLoadDelegateForwarder] webView:[self webView]
1186                                                     didFinishLoadForFrame:self];
1187                     [_private->internalLoadDelegate webFrame:self didFinishLoadWithError:nil];
1188                 }
1189                 
1190                 [[self webView] _progressCompleted: self];
1191  
1192                 return;
1193             }
1194             return;
1195         }
1196         
1197         case WebFrameStateComplete:
1198         {
1199             LOG(Loading, "%@:  checking complete, current state WebFrameStateComplete", [self name]);
1200             // Even if already complete, we might have set a previous item on a frame that
1201             // didn't do any data loading on the past transaction.  Make sure to clear these out.
1202             [_private setPreviousItem:nil];
1203             return;
1204         }
1205     }
1206     
1207     // Yikes!  Serious horkage.
1208     ASSERT_NOT_REACHED();
1209 }
1210
1211 - (void)_handledOnloadEvents
1212 {
1213     [[[self webView] _frameLoadDelegateForwarder] webView:[self webView] didHandleOnloadEventsForFrame:self];
1214 }
1215
1216 // Called every time a resource is completely loaded, or an error is received.
1217 - (void)_checkLoadComplete
1218 {
1219     ASSERT([self webView] != nil);
1220
1221     for (WebFrame *frame = self; frame; frame = [frame parentFrame])
1222         [frame _checkLoadCompleteForThisFrame];
1223 }
1224
1225 - (WebFrameBridge *)_bridge
1226 {
1227     return _private->bridge;
1228 }
1229
1230 - (void)_handleUnimplementablePolicyWithErrorCode:(int)code forURL:(NSURL *)URL
1231 {
1232     NSError *error = [NSError _webKitErrorWithDomain:WebKitErrorDomain code:code URL:URL];
1233     WebView *wv = [self webView];
1234     _private->delegateIsHandlingUnimplementablePolicy = YES;
1235     [[wv _policyDelegateForwarder] webView:wv unableToImplementPolicyWithError:error frame:self];    
1236     _private->delegateIsHandlingUnimplementablePolicy = NO;
1237 }
1238
1239 - (void)_clearProvisionalDataSource
1240 {
1241     [self _setProvisionalDataSource:nil];
1242 }
1243
1244 // helper method that determines whether the subframes described by the item's subitems
1245 // match our own current frameset
1246 - (BOOL)_childFramesMatchItem:(WebHistoryItem *)item
1247 {
1248     NSArray *childItems = [item children];
1249     int numChildItems = [childItems count];
1250     int numChildFrames = [self _childFrameCount];
1251     if (numChildFrames != numChildItems)
1252         return NO;
1253
1254     int i;
1255     for (i = 0; i < numChildItems; i++) {
1256         NSString *itemTargetName = [[childItems objectAtIndex:i] target];
1257         //Search recursive here?
1258         if (![self _immediateChildFrameNamed:itemTargetName])
1259             return NO; // couldn't match the i'th itemTarget
1260     }
1261
1262     return YES; // found matches for all itemTargets
1263 }
1264
1265 - (BOOL)_shouldReloadForCurrent:(NSURL *)currentURL andDestination:(NSURL *)destinationURL
1266 {
1267     return !(([currentURL fragment] || [destinationURL fragment]) &&
1268     [[currentURL _webkit_URLByRemovingFragment] isEqual: [destinationURL _webkit_URLByRemovingFragment]]);
1269 }
1270
1271 // Walk the frame tree and ensure that the URLs match the URLs in the item.
1272 - (BOOL)_URLsMatchItem:(WebHistoryItem *)item
1273 {
1274     NSURL *currentURL = [[[self dataSource] request] URL];
1275
1276     if (![[[item URL] _webkit_URLByRemovingFragment] isEqual:[currentURL _webkit_URLByRemovingFragment]])
1277         return NO;
1278     
1279     NSArray *childItems = [item children];
1280     WebHistoryItem *childItem;
1281     WebFrame *childFrame;
1282     int i, count = [childItems count];
1283     for (i = 0; i < count; i++){
1284         childItem = [childItems objectAtIndex:i];
1285         childFrame = [self _immediateChildFrameNamed:[childItem target]];
1286         if (![childFrame _URLsMatchItem: childItem])
1287             return NO;
1288     }
1289     
1290     return YES;
1291 }
1292
1293 // loads content into this frame, as specified by item
1294 - (void)_loadItem:(WebHistoryItem *)item withLoadType:(WebFrameLoadType)loadType
1295 {
1296     NSURL *itemURL = [item URL];
1297     NSURL *itemOriginalURL = [NSURL _web_URLWithDataAsString:[item originalURLString]];
1298     NSURL *currentURL = [[[self dataSource] request] URL];
1299     NSArray *formData = [item formData];
1300
1301     // Are we navigating to an anchor within the page?
1302     // Note if we have child frames we do a real reload, since the child frames might not
1303     // match our current frame structure, or they might not have the right content.  We could
1304     // check for all that as an additional optimization.
1305     // We also do not do anchor-style navigation if we're posting a form.
1306     
1307     // FIXME: These checks don't match the ones in _loadURL:referrer:loadType:target:triggeringEvent:isFormSubmission:
1308     // Perhaps they should.
1309     if (!formData && ![self _shouldReloadForCurrent:itemURL andDestination:currentURL] && [self _URLsMatchItem:item] )
1310     {
1311 #if 0
1312         // FIXME:  We need to normalize the code paths for anchor navigation.  Something
1313         // like the following line of code should be done, but also accounting for correct
1314         // updates to the back/forward list and scroll position.
1315         // rjw 4/9/03 See 3223929.
1316         [self _loadURL:itemURL referrer:[[[self dataSource] request] HTTPReferrer] loadType:loadType target:nil triggeringEvent:nil form:nil formValues:nil];
1317 #endif
1318         // must do this maintenance here, since we don't go through a real page reload
1319         [self _saveScrollPositionAndViewStateToItem:[_private currentItem]];
1320         // FIXME: form state might want to be saved here too
1321
1322         // FIXME: Perhaps we can use scrollToAnchorWithURL here instead and remove the older scrollToAnchor:?
1323         NSString *anchor = [[item URLString] _webkit_URLFragment];
1324         if (anchor)
1325             [[_private->dataSource _bridge] scrollToAnchor: anchor];
1326     
1327         // must do this maintenance here, since we don't go through a real page reload
1328         [_private setCurrentItem:item];
1329         [self _restoreScrollPositionAndViewState];
1330
1331         // Fake the URL change by updating the data source's request.  This will no longer
1332         // be necessary if we do the better fix described above.
1333         NSMutableURLRequest *hackedRequest = [[[self dataSource] request] mutableCopy];
1334         [hackedRequest setURL: itemURL];
1335         [[self dataSource] __adoptRequest:hackedRequest];
1336         [hackedRequest release];
1337         
1338         [[[self webView] _frameLoadDelegateForwarder] webView:[self webView]
1339                                didChangeLocationWithinPageForFrame:self];
1340         [_private->internalLoadDelegate webFrame:self didFinishLoadWithError:nil];
1341     } else {
1342         // Remember this item so we can traverse any child items as child frames load
1343         [_private setProvisionalItem:item];
1344
1345         WebDataSource *newDataSource;
1346         BOOL inPageCache = NO;
1347         
1348         // Check if we'll be using the page cache.  We only use the page cache
1349         // if one exists and it is less than _backForwardCacheExpirationInterval
1350         // seconds old.  If the cache is expired it gets flushed here.
1351         if ([item hasPageCache]){
1352             NSDictionary *pageCache = [item pageCache];
1353             NSDate *cacheDate = [pageCache objectForKey: WebPageCacheEntryDateKey];
1354             NSTimeInterval delta = [[NSDate date] timeIntervalSinceDate: cacheDate];
1355
1356             if (delta <= [[[self webView] preferences] _backForwardCacheExpirationInterval]){
1357                 newDataSource = [pageCache objectForKey: WebPageCacheDataSourceKey];
1358                 [self _loadDataSource:newDataSource withLoadType:loadType formState:nil];   
1359                 inPageCache = YES;
1360             }         
1361             else {
1362                 LOG (PageCache, "Not restoring page from back/forward cache because cache entry has expired, %@ (%3.5f > %3.5f seconds)\n", [[_private provisionalItem] URL], delta, [[[self webView] preferences] _backForwardCacheExpirationInterval]);
1363                 [item setHasPageCache: NO];
1364             }
1365         }
1366         
1367         if (!inPageCache) {
1368             NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:itemURL];
1369             [self _addExtraFieldsToRequest:request alwaysFromRequest: (formData != nil)?YES:NO];
1370
1371             // If this was a repost that failed the page cache, we might try to repost the form.
1372             NSDictionary *action;
1373             if (formData) {
1374                 [request setHTTPMethod:@"POST"];
1375                 [request _web_setHTTPReferrer:[item formReferrer]];
1376                 webSetHTTPBody(request, formData);
1377                 [request _web_setHTTPContentType:[item formContentType]];
1378
1379                 // Slight hack to test if the WF cache contains the page we're going to.  We want
1380                 // to know this before talking to the policy delegate, since it affects whether we
1381                 // show the DoYouReallyWantToRepost nag.
1382                 //
1383                 // This trick has a small bug (3123893) where we might find a cache hit, but then
1384                 // have the item vanish when we try to use it in the ensuing nav.  This should be
1385                 // extremely rare, but in that case the user will get an error on the navigation.
1386                 [request setCachePolicy:NSURLRequestReturnCacheDataDontLoad];
1387                 NSURLResponse *synchResponse = nil;
1388                 [NSURLConnection sendSynchronousRequest:request returningResponse:&synchResponse error:nil];
1389                 if (synchResponse == nil) { 
1390                     // Not in WF cache
1391                     [request setCachePolicy:NSURLRequestReloadIgnoringCacheData];
1392                     action = [self _actionInformationForNavigationType:WebNavigationTypeFormResubmitted event:nil originalURL:itemURL];
1393                 } else {
1394                     // We can use the cache, don't use navType=resubmit
1395                     action = [self _actionInformationForLoadType:loadType isFormSubmission:NO event:nil originalURL:itemURL];
1396                 }
1397             } else {
1398                 switch (loadType) {
1399                     case WebFrameLoadTypeReload:
1400                         [request setCachePolicy:NSURLRequestReloadIgnoringCacheData];
1401                         break;
1402                     case WebFrameLoadTypeBack:
1403                     case WebFrameLoadTypeForward:
1404                     case WebFrameLoadTypeIndexedBackForward:
1405                         if (![[itemURL scheme] isEqual:@"https"]) {
1406                             [request setCachePolicy:NSURLRequestReturnCacheDataElseLoad];
1407                         }
1408                         break;
1409                     case WebFrameLoadTypeStandard:
1410                     case WebFrameLoadTypeInternal:
1411                         // no-op: leave as protocol default
1412                         // FIXME:  I wonder if we ever hit this case
1413                         break;
1414                     case WebFrameLoadTypeSame:
1415                     case WebFrameLoadTypeReloadAllowingStaleData:
1416                     default:
1417                         ASSERT_NOT_REACHED();
1418                 }
1419
1420                 action = [self _actionInformationForLoadType:loadType isFormSubmission:NO event:nil originalURL:itemOriginalURL];
1421             }
1422
1423             [self _loadRequest:request triggeringAction:action loadType:loadType formState:nil];
1424             [request release];
1425         }
1426     }
1427 }
1428
1429 // The general idea here is to traverse the frame tree and the item tree in parallel,
1430 // tracking whether each frame already has the content the item requests.  If there is
1431 // a match (by URL), we just restore scroll position and recurse.  Otherwise we must
1432 // reload that frame, and all its kids.
1433 - (void)_recursiveGoToItem:(WebHistoryItem *)item fromItem:(WebHistoryItem *)fromItem withLoadType:(WebFrameLoadType)type
1434 {
1435     NSURL *itemURL = [item URL];
1436     NSURL *currentURL = [[[self dataSource] request] URL];
1437
1438     // Always reload the target frame of the item we're going to.  This ensures that we will
1439     // do -some- load for the transition, which means a proper notification will be posted
1440     // to the app.
1441     // The exact URL has to match, including fragment.  We want to go through the _load
1442     // method, even if to do a within-page navigation.
1443     // The current frame tree and the frame tree snapshot in the item have to match.
1444     if (![item isTargetItem] &&
1445         [itemURL isEqual:currentURL] &&
1446         (([self name] == nil && [item target] == nil) ||[[self name] isEqualToString:[item target]]) &&
1447         [self _childFramesMatchItem:item])
1448     {
1449         // This content is good, so leave it alone and look for children that need reloading
1450
1451         // Save form state (works from currentItem, since prevItem is nil)
1452         ASSERT(![_private previousItem]);
1453         [_private->bridge saveDocumentState];
1454         [self _saveScrollPositionAndViewStateToItem:[_private currentItem]];
1455         
1456         [_private setCurrentItem:item];
1457
1458         // Restore form state (works from currentItem)
1459         [_private->bridge restoreDocumentState];
1460         // Restore the scroll position (taken in favor of going back to the anchor)
1461         [self _restoreScrollPositionAndViewState];
1462         
1463         NSArray *childItems = [item children];
1464         int numChildItems = childItems ? [childItems count] : 0;
1465         int i;
1466         for (i = numChildItems - 1; i >= 0; i--) {
1467             WebHistoryItem *childItem = [childItems objectAtIndex:i];
1468             NSString *childName = [childItem target];
1469             WebHistoryItem *fromChildItem = [fromItem childItemWithName:childName];
1470             ASSERT(fromChildItem || [fromItem isTargetItem]);
1471             WebFrame *childFrame = [self _immediateChildFrameNamed:childName];
1472             ASSERT(childFrame);
1473             [childFrame _recursiveGoToItem:childItem fromItem:fromChildItem withLoadType:type];
1474         }
1475     } else {
1476         // We need to reload the content
1477         [self _loadItem:item withLoadType:type];
1478     }
1479 }
1480
1481 // Main funnel for navigating to a previous location (back/forward, non-search snap-back)
1482 // This includes recursion to handle loading into framesets properly
1483 - (void)_goToItem:(WebHistoryItem *)item withLoadType:(WebFrameLoadType)type
1484 {
1485     ASSERT(![self parentFrame]);
1486     // shouldGoToHistoryItem is a private delegate method. This is needed to fix:
1487     // <rdar://problem/3951283> can view pages from the back/forward cache that should be disallowed by Parental Controls
1488     // Ultimately, history item navigations should go through the policy delegate. That's covered in:
1489     // <rdar://problem/3979539> back/forward cache navigations should consult policy delegate
1490     if ([[[self webView] _policyDelegateForwarder] webView:[self webView] shouldGoToHistoryItem:item]) {    
1491         WebBackForwardList *backForwardList = [[self webView] backForwardList];
1492         WebHistoryItem *currItem = [backForwardList currentItem];
1493         // Set the BF cursor before commit, which lets the user quickly click back/forward again.
1494         // - plus, it only makes sense for the top level of the operation through the frametree,
1495         // as opposed to happening for some/one of the page commits that might happen soon
1496         [backForwardList goToItem:item];
1497         [self _recursiveGoToItem:item fromItem:currItem withLoadType:type];
1498     }
1499 }
1500
1501 - (void)_loadRequest:(NSURLRequest *)request triggeringAction:(NSDictionary *)action loadType:(WebFrameLoadType)loadType formState:(WebFormState *)formState
1502 {
1503     WebDataSource *newDataSource = [[WebDataSource alloc] initWithRequest:request];
1504     [newDataSource _setTriggeringAction:action];
1505
1506     [newDataSource _setOverrideEncoding:[[self dataSource] _overrideEncoding]];
1507
1508     [self _loadDataSource:newDataSource withLoadType:loadType formState:formState];
1509
1510     [newDataSource release];
1511 }
1512
1513 -(NSDictionary *)_actionInformationForNavigationType:(WebNavigationType)navigationType event:(NSEvent *)event originalURL:(NSURL *)URL
1514 {
1515     switch ([event type]) {
1516         case NSLeftMouseDown:
1517         case NSRightMouseDown:
1518         case NSOtherMouseDown:
1519         case NSLeftMouseUp:
1520         case NSRightMouseUp:
1521         case NSOtherMouseUp:
1522         {
1523             NSView *topViewInEventWindow = [[event window] contentView];
1524             NSView *viewContainingPoint = [topViewInEventWindow hitTest:[topViewInEventWindow convertPoint:[event locationInWindow] fromView:nil]];
1525             while (viewContainingPoint != nil) {
1526                 if ([viewContainingPoint isKindOfClass:[WebHTMLView class]]) {
1527                     break;
1528                 }
1529                 viewContainingPoint = [viewContainingPoint superview];
1530             }
1531             if (viewContainingPoint != nil) {
1532                 NSPoint point = [viewContainingPoint convertPoint:[event locationInWindow] fromView:nil];
1533                 NSDictionary *elementInfo = [(WebHTMLView *)viewContainingPoint elementAtPoint:point];
1534         
1535                 return [NSDictionary dictionaryWithObjectsAndKeys:
1536                     [NSNumber numberWithInt:navigationType], WebActionNavigationTypeKey,
1537                     elementInfo, WebActionElementKey,
1538                     [NSNumber numberWithInt:[event buttonNumber]], WebActionButtonKey,
1539                     [NSNumber numberWithInt:[event modifierFlags]], WebActionModifierFlagsKey,
1540                     URL, WebActionOriginalURLKey,
1541                     nil];
1542             }
1543         }
1544             
1545         // fall through
1546         
1547         default:
1548             return [NSDictionary dictionaryWithObjectsAndKeys:
1549                 [NSNumber numberWithInt:navigationType], WebActionNavigationTypeKey,
1550                 [NSNumber numberWithInt:[event modifierFlags]], WebActionModifierFlagsKey,
1551                 URL, WebActionOriginalURLKey,
1552                 nil];
1553     }
1554 }
1555
1556 -(NSDictionary *)_actionInformationForLoadType:(WebFrameLoadType)loadType isFormSubmission:(BOOL)isFormSubmission event:(NSEvent *)event originalURL:(NSURL *)URL
1557 {
1558     WebNavigationType navType;
1559     if (isFormSubmission) {
1560         navType = WebNavigationTypeFormSubmitted;
1561     } else if (event == nil) {
1562         if (loadType == WebFrameLoadTypeReload) {
1563             navType = WebNavigationTypeReload;
1564         } else if (loadType == WebFrameLoadTypeForward
1565                    || loadType == WebFrameLoadTypeBack
1566                    || loadType == WebFrameLoadTypeIndexedBackForward) {
1567             navType = WebNavigationTypeBackForward;
1568         } else {
1569             navType = WebNavigationTypeOther;
1570         }
1571     } else {
1572         navType = WebNavigationTypeLinkClicked;
1573     }
1574     return [self _actionInformationForNavigationType:navType event:event originalURL:URL];
1575 }
1576
1577 - (void)_invalidatePendingPolicyDecisionCallingDefaultAction:(BOOL)call
1578 {
1579     [_private->listener _invalidate];
1580     [_private->listener release];
1581     _private->listener = nil;
1582
1583     NSURLRequest *request = _private->policyRequest;
1584     NSString *frameName = _private->policyFrameName;
1585     id target = _private->policyTarget;
1586     SEL selector = _private->policySelector;
1587     WebFormState *formState = _private->policyFormState;
1588
1589     _private->policyRequest = nil;
1590     _private->policyFrameName = nil;
1591     _private->policyTarget = nil;
1592     _private->policySelector = nil;
1593     _private->policyFormState = nil;
1594
1595     if (call) {
1596         if (frameName) {
1597             [target performSelector:selector withObject:nil withObject:nil withObject:nil];
1598         } else {
1599             [target performSelector:selector withObject:nil withObject:nil];
1600         }
1601     }
1602
1603     [request release];
1604     [frameName release];
1605     [target release];
1606     [formState release];
1607 }
1608
1609 - (void)_setPolicyDataSource:(WebDataSource *)dataSource
1610 {
1611     [dataSource retain];
1612     [_private->policyDataSource release];
1613     _private->policyDataSource = dataSource;
1614 }
1615
1616 - (void)_checkNewWindowPolicyForRequest:(NSURLRequest *)request action:(NSDictionary *)action frameName:(NSString *)frameName formState:(WebFormState *)formState andCall:(id)target withSelector:(SEL)selector
1617 {
1618     WebPolicyDecisionListener *listener = [[WebPolicyDecisionListener alloc]
1619         _initWithTarget:self action:@selector(_continueAfterNewWindowPolicy:)];
1620
1621     _private->policyRequest = [request retain];
1622     _private->policyTarget = [target retain];
1623     _private->policyFrameName = [frameName retain];
1624     _private->policySelector = selector;
1625     _private->listener = [listener retain];
1626     _private->policyFormState = [formState retain];
1627
1628     WebView *wv = [self webView];
1629     [[wv _policyDelegateForwarder] webView:wv
1630             decidePolicyForNewWindowAction:action
1631                                    request:request
1632                               newFrameName:frameName
1633                           decisionListener:listener];
1634     
1635     [listener release];
1636 }
1637
1638 -(void)_continueAfterNewWindowPolicy:(WebPolicyAction)policy
1639 {
1640     NSURLRequest *request = [[_private->policyRequest retain] autorelease];
1641     NSString *frameName = [[_private->policyFrameName retain] autorelease];
1642     id target = [[_private->policyTarget retain] autorelease];
1643     SEL selector = _private->policySelector;
1644     WebFormState *formState = [[_private->policyFormState retain] autorelease];
1645
1646     // will release _private->policy* objects, hence the above retains
1647     [self _invalidatePendingPolicyDecisionCallingDefaultAction:NO];
1648
1649     BOOL shouldContinue = NO;
1650
1651     switch (policy) {
1652     case WebPolicyIgnore:
1653         break;
1654     case WebPolicyDownload:
1655         // FIXME: should download full request
1656         [[self webView] _downloadURL:[request URL]];
1657         break;
1658     case WebPolicyUse:
1659         shouldContinue = YES;
1660         break;
1661     default:
1662         ASSERT_NOT_REACHED();
1663     }
1664
1665     [target performSelector:selector withObject:(shouldContinue ? request : nil) withObject:frameName withObject:formState];
1666 }
1667
1668 - (void)_checkNavigationPolicyForRequest:(NSURLRequest *)request
1669                               dataSource:(WebDataSource *)dataSource
1670                                formState:(WebFormState *)formState
1671                                  andCall:(id)target
1672                             withSelector:(SEL)selector
1673 {    
1674     NSDictionary *action = [dataSource _triggeringAction];
1675     if (action == nil) {
1676         action = [self _actionInformationForNavigationType:WebNavigationTypeOther event:nil originalURL:[request URL]];
1677         [dataSource _setTriggeringAction:action];
1678     }
1679         
1680     // Don't ask more than once for the same request or if we are loading an empty URL.
1681     // This avoids confusion on the part of the client.
1682     if ([request isEqual:[dataSource _lastCheckedRequest]] || [[request URL] _web_isEmpty]) {
1683         [target performSelector:selector withObject:request withObject:nil];
1684         return;
1685     }
1686     
1687     // We are always willing to show alternate content for unreachable URLs;
1688     // treat it like a reload so it maintains the right state for b/f list.
1689     if ([request _webDataRequestUnreachableURL] != nil) {
1690         if (_private->policyLoadType == WebFrameLoadTypeForward
1691             || _private->policyLoadType == WebFrameLoadTypeBack
1692             || _private->policyLoadType == WebFrameLoadTypeIndexedBackForward) {
1693             _private->policyLoadType = WebFrameLoadTypeReload;
1694         }
1695         [target performSelector:selector withObject:request withObject:nil];
1696         return;
1697     }
1698     
1699     [dataSource _setLastCheckedRequest:request];
1700
1701     WebPolicyDecisionListener *listener = [[WebPolicyDecisionListener alloc] _initWithTarget:self action:@selector(_continueAfterNavigationPolicy:)];
1702     
1703     ASSERT(_private->policyRequest == nil);
1704     _private->policyRequest = [request retain];
1705     ASSERT(_private->policyTarget == nil);
1706     _private->policyTarget = [target retain];
1707     _private->policySelector = selector;
1708     ASSERT(_private->listener == nil);
1709     _private->listener = [listener retain];
1710     ASSERT(_private->policyFormState == nil);
1711     _private->policyFormState = [formState retain];
1712
1713     WebView *wv = [self webView];
1714     _private->delegateIsDecidingNavigationPolicy = YES;
1715     [[wv _policyDelegateForwarder] webView:wv
1716            decidePolicyForNavigationAction:action
1717                                    request:request
1718                                      frame:self
1719                           decisionListener:listener];
1720     _private->delegateIsDecidingNavigationPolicy = NO;
1721     
1722     [listener release];
1723 }
1724
1725 -(void)_continueAfterNavigationPolicy:(WebPolicyAction)policy
1726 {
1727     NSURLRequest *request = [[_private->policyRequest retain] autorelease];
1728     id target = [[_private->policyTarget retain] autorelease];
1729     SEL selector = _private->policySelector;
1730     WebFormState *formState = [[_private->policyFormState retain] autorelease];
1731     
1732     // will release _private->policy* objects, hence the above retains
1733     [self _invalidatePendingPolicyDecisionCallingDefaultAction:NO];
1734
1735     BOOL shouldContinue = NO;
1736
1737     switch (policy) {
1738     case WebPolicyIgnore:
1739         break;
1740     case WebPolicyDownload:
1741         // FIXME: should download full request
1742         [[self webView] _downloadURL:[request URL]];
1743         break;
1744     case WebPolicyUse:
1745         if (![WebView _canHandleRequest:request]) {
1746             [self _handleUnimplementablePolicyWithErrorCode:WebKitErrorCannotShowURL forURL:[request URL]];
1747         } else {
1748             shouldContinue = YES;
1749         }
1750         break;
1751     default:
1752         ASSERT_NOT_REACHED();
1753     }
1754
1755     [target performSelector:selector withObject:(shouldContinue ? request : nil) withObject:formState];
1756 }
1757
1758 -(void)_continueFragmentScrollAfterNavigationPolicy:(NSURLRequest *)request formState:(WebFormState *)formState
1759 {
1760     if (!request) {
1761         return;
1762     }
1763
1764     NSURL *URL = [request URL];
1765     WebDataSource *dataSrc = [self dataSource];
1766
1767     BOOL isRedirect = _private->quickRedirectComing;
1768     LOG(Redirect, "%@(%p) _private->quickRedirectComing = %d", [self name], self, (int)_private->quickRedirectComing);
1769     _private->quickRedirectComing = NO;
1770
1771     [dataSrc _setURL:URL];
1772     if (!isRedirect && ![self _shouldTreatURLAsSameAsCurrent:URL]) {
1773         // NB: must happen after _setURL, since we add based on the current request.
1774         // Must also happen before we openURL and displace the scroll position, since
1775         // adding the BF item will save away scroll state.
1776
1777         // NB2:  If we were loading a long, slow doc, and the user anchor nav'ed before
1778         // it was done, currItem is now set the that slow doc, and prevItem is whatever was
1779         // before it.  Adding the b/f item will bump the slow doc down to prevItem, even
1780         // though its load is not yet done.  I think this all works out OK, for one because
1781         // we have already saved away the scroll and doc state for the long slow load,
1782         // but it's not an obvious case.
1783         [self _addBackForwardItemClippedAtTarget:NO];
1784     }
1785
1786     [_private->bridge scrollToAnchorWithURL:URL];
1787     
1788     if (!isRedirect) {
1789         // This will clear previousItem from the rest of the frame tree tree that didn't
1790         // doing any loading.  We need to make a pass on this now, since for anchor nav
1791         // we'll not go through a real load and reach Completed state
1792         [self _checkLoadComplete];
1793     }
1794
1795     [[[self webView] _frameLoadDelegateForwarder] webView:[self webView]
1796                       didChangeLocationWithinPageForFrame:self];
1797     [_private->internalLoadDelegate webFrame:self didFinishLoadWithError:nil];
1798 }
1799
1800 - (void)_addExtraFieldsToRequest:(NSMutableURLRequest *)request alwaysFromRequest: (BOOL)f
1801 {
1802     [request _web_setHTTPUserAgent:[[self webView] userAgentForURL:[request URL]]];
1803     
1804     // Don't set the cookie policy URL if it's already been set.
1805     if ([request mainDocumentURL] == nil){
1806         if (self == [[self webView] mainFrame] || f) {
1807             [request setMainDocumentURL:[request URL]];
1808         } else {
1809             [request setMainDocumentURL:[[[[self webView] mainFrame] dataSource] _URL]];
1810         }
1811     }
1812 }
1813
1814 - (void)_continueLoadRequestAfterNewWindowPolicy:(NSURLRequest *)request frameName:(NSString *)frameName formState:(WebFormState *)formState
1815 {
1816     if (!request) {
1817         return;
1818     }
1819     
1820     WebView *webView = nil;
1821     WebView *currentWebView = [self webView];
1822     id wd = [currentWebView UIDelegate];
1823     if ([wd respondsToSelector:@selector(webView:createWebViewWithRequest:)])
1824         webView = [wd webView:currentWebView createWebViewWithRequest:nil];
1825     else
1826         webView = [[WebDefaultUIDelegate sharedUIDelegate] webView:currentWebView createWebViewWithRequest:nil];
1827         
1828
1829     WebFrame *frame = [webView mainFrame];
1830     [[frame _bridge] setName:frameName];
1831
1832     [[webView _UIDelegateForwarder] webViewShow:webView];
1833
1834     [[self _bridge] setOpener:[frame _bridge]];
1835     [frame _loadRequest:request triggeringAction:nil loadType:WebFrameLoadTypeStandard formState:formState];
1836 }
1837
1838
1839 // main funnel for navigating via callback from WebCore (e.g., clicking a link, redirect)
1840 - (void)_loadURL:(NSURL *)URL referrer:(NSString *)referrer loadType:(WebFrameLoadType)loadType target:(NSString *)target triggeringEvent:(NSEvent *)event form:(DOMElement *)form formValues:(NSDictionary *)values
1841 {
1842     BOOL isFormSubmission = (values != nil);
1843
1844     NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:URL];
1845     [request _web_setHTTPReferrer:referrer];
1846     [self _addExtraFieldsToRequest:request alwaysFromRequest: (event != nil || isFormSubmission)];
1847     if (loadType == WebFrameLoadTypeReload) {
1848         [request setCachePolicy:NSURLRequestReloadIgnoringCacheData];
1849     }
1850
1851     // I believe this is never called with LoadSame.  If it is, we probably want to set the cache
1852     // policy of LoadFromOrigin, but I didn't test that.
1853     ASSERT(loadType != WebFrameLoadTypeSame);
1854
1855     NSDictionary *action = [self _actionInformationForLoadType:loadType isFormSubmission:isFormSubmission event:event originalURL:URL];
1856     WebFormState *formState = nil;
1857     if (form && values) {
1858         formState = [[WebFormState alloc] initWithForm:form values:values sourceFrame:self];
1859     }
1860
1861     if (target != nil) {
1862         WebFrame *targetFrame = [self findFrameNamed:target];
1863         if (targetFrame != nil) {
1864             [targetFrame _loadURL:URL referrer:referrer loadType:loadType target:nil triggeringEvent:event form:form formValues:values];
1865         } else {
1866             [self _checkNewWindowPolicyForRequest:request
1867                                     action:action
1868                                  frameName:target
1869                                  formState:formState
1870                                    andCall:self
1871                               withSelector:@selector(_continueLoadRequestAfterNewWindowPolicy:frameName:formState:)];
1872         }
1873         [request release];
1874         [formState release];
1875         return;
1876     }
1877
1878     WebDataSource *oldDataSource = [[self dataSource] retain];
1879
1880     BOOL sameURL = [self _shouldTreatURLAsSameAsCurrent:URL];
1881
1882     // Make sure to do scroll to anchor processing even if the URL is
1883     // exactly the same so pages with '#' links and DHTML side effects
1884     // work properly.
1885     if (!isFormSubmission
1886         && loadType != WebFrameLoadTypeReload
1887         && loadType != WebFrameLoadTypeSame
1888         && ![self _shouldReloadForCurrent:URL andDestination:[_private->bridge URL]]
1889
1890         // We don't want to just scroll if a link from within a
1891         // frameset is trying to reload the frameset into _top.
1892         && ![_private->bridge isFrameSet]) {
1893         
1894         // Just do anchor navigation within the existing content.
1895         
1896         // We don't do this if we are submitting a form, explicitly reloading,
1897         // currently displaying a frameset, or if the new URL does not have a fragment.
1898         // These rules are based on what KHTML was doing in KHTMLPart::openURL.
1899         
1900         
1901         // FIXME: What about load types other than Standard and Reload?
1902
1903         [oldDataSource _setTriggeringAction:action];
1904         [self _invalidatePendingPolicyDecisionCallingDefaultAction:YES];
1905         [self _checkNavigationPolicyForRequest:request
1906                                     dataSource:oldDataSource
1907                                      formState:formState
1908                                        andCall:self
1909                                   withSelector:@selector(_continueFragmentScrollAfterNavigationPolicy:formState:)];
1910     } else {
1911         // must grab this now, since this load may stop the previous load and clear this flag
1912         BOOL isRedirect = _private->quickRedirectComing;
1913         [self _loadRequest:request triggeringAction:action loadType:loadType formState:formState];
1914         if (isRedirect) {
1915             LOG(Redirect, "%@(%p) _private->quickRedirectComing was %d", [self name], self, (int)isRedirect);
1916             _private->quickRedirectComing = NO;
1917             [[self provisionalDataSource] _setIsClientRedirect:YES];
1918         } else if (sameURL) {
1919             // Example of this case are sites that reload the same URL with a different cookie
1920             // driving the generated content, or a master frame with links that drive a target
1921             // frame, where the user has clicked on the same link repeatedly.
1922             [self _setLoadType:WebFrameLoadTypeSame];
1923         }            
1924     }
1925
1926     [request release];
1927     [oldDataSource release];
1928     [formState release];
1929 }
1930
1931 - (void)_loadURL:(NSURL *)URL referrer:(NSString *)referrer intoChild:(WebFrame *)childFrame
1932 {
1933     WebHistoryItem *parentItem = [_private currentItem];
1934     NSArray *childItems = [parentItem children];
1935     WebFrameLoadType loadType = [self _loadType];
1936     WebFrameLoadType childLoadType = WebFrameLoadTypeInternal;
1937     WebHistoryItem *childItem = nil;
1938
1939     // If we're moving in the backforward list, we might want to replace the content
1940     // of this child frame with whatever was there at that point.
1941     // Reload will maintain the frame contents, LoadSame will not.
1942     if (childItems &&
1943         (loadType == WebFrameLoadTypeForward
1944          || loadType == WebFrameLoadTypeBack
1945          || loadType == WebFrameLoadTypeIndexedBackForward
1946          || loadType == WebFrameLoadTypeReload
1947          || loadType == WebFrameLoadTypeReloadAllowingStaleData))
1948     {
1949         childItem = [parentItem childItemWithName:[childFrame name]];
1950         if (childItem) {
1951             // Use the original URL to ensure we get all the side-effects, such as
1952             // onLoad handlers, of any redirects that happened. An example of where
1953             // this is needed is Radar 3213556.
1954             URL = [NSURL _web_URLWithDataAsString:[childItem originalURLString]];
1955             // These behaviors implied by these loadTypes should apply to the child frames
1956             childLoadType = loadType;
1957
1958             if (loadType == WebFrameLoadTypeForward
1959                 || loadType == WebFrameLoadTypeBack
1960                 || loadType == WebFrameLoadTypeIndexedBackForward)
1961             {
1962                 // For back/forward, remember this item so we can traverse any child items as child frames load
1963                 [childFrame->_private setProvisionalItem:childItem];
1964             } else {
1965                 // For reload, just reinstall the current item, since a new child frame was created but we won't be creating a new BF item
1966                 [childFrame->_private setCurrentItem:childItem];
1967             }
1968         }
1969     }
1970
1971     WebArchive *archive = [[self dataSource] _popSubframeArchiveWithName:[childFrame name]];
1972     if (archive) {
1973         [childFrame loadArchive:archive];
1974     } else {
1975         [childFrame _loadURL:URL referrer:referrer loadType:childLoadType target:nil triggeringEvent:nil form:nil formValues:nil];
1976     }
1977 }
1978
1979 - (void)_postWithURL:(NSURL *)URL referrer:(NSString *)referrer target:(NSString *)target data:(NSArray *)postData contentType:(NSString *)contentType triggeringEvent:(NSEvent *)event form:(DOMElement *)form formValues:(NSDictionary *)values
1980 {
1981     // When posting, use the NSURLRequestReloadIgnoringCacheData load flag.
1982     // This prevents a potential bug which may cause a page with a form that uses itself
1983     // as an action to be returned from the cache without submitting.
1984
1985     // FIXME: Where's the code that implements what the comment above says?
1986
1987     NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:URL];
1988     [self _addExtraFieldsToRequest:request alwaysFromRequest:YES];
1989     [request _web_setHTTPReferrer:referrer];
1990     [request setHTTPMethod:@"POST"];
1991     webSetHTTPBody(request, postData);
1992     [request _web_setHTTPContentType:contentType];
1993
1994     NSDictionary *action = [self _actionInformationForLoadType:WebFrameLoadTypeStandard isFormSubmission:YES event:event originalURL:URL];
1995     WebFormState *formState = nil;
1996     if (form && values) {
1997         formState = [[WebFormState alloc] initWithForm:form values:values sourceFrame:self];
1998     }
1999
2000     if (target != nil) {
2001         WebFrame *targetFrame = [self findFrameNamed:target];
2002
2003         if (targetFrame != nil) {
2004             [targetFrame _loadRequest:request triggeringAction:action loadType:WebFrameLoadTypeStandard formState:formState];
2005         } else {
2006             [self _checkNewWindowPolicyForRequest:request action:action frameName:target formState:formState andCall:self withSelector:@selector(_continueLoadRequestAfterNewWindowPolicy:frameName:formState:)];
2007         }
2008         [request release];
2009         [formState release];
2010         return;
2011     }
2012
2013     [self _loadRequest:request triggeringAction:action loadType:WebFrameLoadTypeStandard formState:formState];
2014
2015     [request release];
2016     [formState release];
2017 }
2018
2019 - (void)_clientRedirectedTo:(NSURL *)URL delay:(NSTimeInterval)seconds fireDate:(NSDate *)date lockHistory:(BOOL)lockHistory isJavaScriptFormAction:(BOOL)isJavaScriptFormAction
2020 {
2021     LOG(Redirect, "%@(%p) Client redirect to: %@, [self dataSource] = %p, lockHistory = %d, isJavaScriptFormAction = %d", [self name], self, URL, [self dataSource], (int)lockHistory, (int)isJavaScriptFormAction);
2022
2023     [[[self webView] _frameLoadDelegateForwarder] webView:[self webView]
2024                                 willPerformClientRedirectToURL:URL
2025                                                          delay:seconds
2026                                                       fireDate:date
2027                                                       forFrame:self];
2028                                                       
2029     // Remember that we sent a redirect notification to the frame load delegate so that when we commit
2030     // the next provisional load, we can send a corresponding -webView:didCancelClientRedirectForFrame:
2031     _private->sentRedirectNotification = YES;
2032     
2033     // If a "quick" redirect comes in an, we set a special mode so we treat the next
2034     // load as part of the same navigation.
2035
2036     if (![self dataSource] || isJavaScriptFormAction) {
2037         // If we don't have a dataSource, we have no "original" load on which to base a redirect,
2038         // so we better just treat the redirect as a normal load.
2039         _private->quickRedirectComing = NO;
2040         LOG(Redirect, "%@(%p) _private->quickRedirectComing = %d", [self name], self, (int)_private->quickRedirectComing);
2041     } else {
2042         _private->quickRedirectComing = lockHistory;
2043         LOG(Redirect, "%@(%p) _private->quickRedirectComing = %d", [self name], self, (int)_private->quickRedirectComing);
2044     }
2045 }
2046
2047 - (void)_clientRedirectCancelledOrFinished:(BOOL)cancelWithLoadInProgress
2048 {
2049     // Note that -webView:didCancelClientRedirectForFrame: is called on the frame load delegate even if
2050     // the redirect succeeded.  We should either rename this API, or add a new method, like
2051     // -webView:didFinishClientRedirectForFrame:
2052     [[[self webView] _frameLoadDelegateForwarder] webView:[self webView]
2053                                didCancelClientRedirectForFrame:self];
2054     if (!cancelWithLoadInProgress)
2055         _private->quickRedirectComing = NO;
2056         
2057     _private->sentRedirectNotification = NO;
2058     
2059     LOG(Redirect, "%@(%p) _private->quickRedirectComing = %d", [self name], self, (int)_private->quickRedirectComing);
2060 }
2061
2062 - (void)_setTitle:(NSString *)title
2063 {
2064     [[_private currentItem] setTitle:title];
2065 }
2066
2067 - (void)_saveScrollPositionAndViewStateToItem:(WebHistoryItem *)item
2068 {
2069     if (item) {
2070         NSView <WebDocumentView> *docView = [[self frameView] documentView];
2071         NSView *parent = [docView superview];
2072         // we might already be detached when this is called from detachFromParent, in which
2073         // case we don't want to override real data earlier gathered with (0,0)
2074         if (parent) {
2075             NSPoint point;
2076             if ([docView conformsToProtocol:@protocol(_WebDocumentViewState)]) {
2077                 // The view has it's own idea of where it is scrolled to, perhaps because it contains its own
2078                 // ScrollView instead of using the one provided by the WebFrame
2079                 point = [(id <_WebDocumentViewState>)docView scrollPoint];
2080                 [item setViewState:[(id <_WebDocumentViewState>)docView viewState]];
2081             } else {
2082                 // Parent is the clipview of the DynamicScrollView the WebFrame installs
2083                 ASSERT([parent isKindOfClass:[NSClipView class]]);
2084                 point = [parent bounds].origin;
2085             }
2086             [item setScrollPoint:point];
2087         }
2088     }
2089 }
2090
2091 /*
2092     There is a race condition between the layout and load completion that affects restoring the scroll position.
2093     We try to restore the scroll position at both the first layout and upon load completion.
2094
2095     1) If first layout happens before the load completes, we want to restore the scroll position then so that the
2096        first time we draw the page is already scrolled to the right place, instead of starting at the top and later
2097        jumping down.  It is possible that the old scroll position is past the part of the doc laid out so far, in
2098        which case the restore silent fails and we will fix it in when we try to restore on doc completion.
2099     2) If the layout happens after the load completes, the attempt to restore at load completion time silently
2100        fails.  We then successfully restore it when the layout happens.
2101  */
2102
2103 - (void)_restoreScrollPositionAndViewState
2104 {
2105     ASSERT([_private currentItem]);
2106     NSView <WebDocumentView> *docView = [[self frameView] documentView];
2107     NSPoint point = [[_private currentItem] scrollPoint];
2108     if ([docView conformsToProtocol:@protocol(_WebDocumentViewState)]) {        
2109         id state = [[_private currentItem] viewState];
2110         if (state) {
2111             [(id <_WebDocumentViewState>)docView setViewState:state];
2112         }
2113         
2114         [(id <_WebDocumentViewState>)docView setScrollPoint:point];
2115     } else {
2116         [docView scrollPoint:point];
2117     }
2118 }
2119
2120 - (void)_defersCallbacksChanged
2121 {
2122     for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self]) {
2123         [[frame provisionalDataSource] _defersCallbacksChanged];
2124         [[frame dataSource] _defersCallbacksChanged];
2125     }
2126 }
2127
2128 - (void)_viewWillMoveToHostWindow:(NSWindow *)hostWindow
2129 {
2130     for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self])
2131         [[[frame frameView] documentView] viewWillMoveToHostWindow:hostWindow];
2132 }
2133
2134 - (void)_viewDidMoveToHostWindow
2135 {
2136     for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self])
2137         [[[frame frameView] documentView] viewDidMoveToHostWindow];
2138 }
2139
2140 - (void)_reloadAllowingStaleDataWithOverrideEncoding:(NSString *)encoding
2141 {
2142     WebDataSource *dataSource = [self dataSource];
2143     if (dataSource == nil) {
2144         return;
2145     }
2146
2147     NSMutableURLRequest *request = [[dataSource request] mutableCopy];
2148     NSURL *unreachableURL = [dataSource unreachableURL];
2149     if (unreachableURL != nil) {
2150         [request setURL:unreachableURL];
2151     }
2152     [request setCachePolicy:NSURLRequestReturnCacheDataElseLoad];
2153     WebDataSource *newDataSource = [[WebDataSource alloc] initWithRequest:request];
2154     [request release];
2155     
2156     [newDataSource _setOverrideEncoding:encoding];
2157
2158     [self _loadDataSource:newDataSource withLoadType:WebFrameLoadTypeReloadAllowingStaleData formState:nil];
2159     
2160     [newDataSource release];
2161 }
2162
2163 - (void)_addChild:(WebFrame *)child
2164 {
2165     [[self _bridge] appendChild:[child _bridge]];
2166     [[child dataSource] _setOverrideEncoding:[[self dataSource] _overrideEncoding]];  
2167 }
2168
2169 - (void)_resetBackForwardList
2170 {
2171     // Note this doesn't verify the current load type as a b/f operation because it is called from
2172     // a subframe in the case of a delegate bailing out of the nav before it even gets to provisional state.
2173     ASSERT(self == [[self webView] mainFrame]);
2174     WebHistoryItem *resetItem = [_private currentItem];
2175     if (resetItem)
2176         [[[self webView] backForwardList] goToItem:resetItem];
2177 }
2178
2179 // If we bailed out of a b/f navigation, we might need to set the b/f cursor back to the current
2180 // item, because we optimistically move it right away at the start of the operation. But when
2181 // alternate content is loaded for an unreachableURL, we don't want to reset the b/f cursor.
2182 // Return the item that we would reset to, so we can decide later whether to actually reset.
2183 - (WebHistoryItem *)_currentBackForwardListItemToResetTo
2184 {
2185     WebFrameLoadType loadType = [self _loadType];
2186     if ((loadType == WebFrameLoadTypeForward
2187          || loadType == WebFrameLoadTypeBack
2188          || loadType == WebFrameLoadTypeIndexedBackForward)
2189         && self == [[self webView] mainFrame]) {
2190         return [_private currentItem];
2191     }
2192     return nil;
2193 }
2194
2195 - (WebHistoryItem *)_itemForSavingDocState
2196 {
2197     // For a standard page load, we will have a previous item set, which will be used to
2198     // store the form state.  However, in some cases we will have no previous item, and
2199     // the current item is the right place to save the state.  One example is when we
2200     // detach a bunch of frames because we are navigating from a site with frames to
2201     // another site.  Another is when saving the frame state of a frame that is not the
2202     // target of the current navigation (if we even decide to save with that granularity).
2203
2204     // Because of previousItem's "masking" of currentItem for this purpose, it's important
2205     // that previousItem be cleared at the end of a page transition.  We leverage the
2206     // checkLoadComplete recursion to achieve this goal.
2207
2208     WebHistoryItem *result = [_private previousItem] ? [_private previousItem] : [_private currentItem];
2209     return result;
2210 }
2211
2212 - (WebHistoryItem *)_itemForRestoringDocState
2213 {
2214     switch ([self _loadType]) {
2215         case WebFrameLoadTypeReload:
2216         case WebFrameLoadTypeReloadAllowingStaleData:
2217         case WebFrameLoadTypeSame:
2218         case WebFrameLoadTypeReplace:
2219             // Don't restore any form state on reload or loadSame
2220             return nil;
2221         case WebFrameLoadTypeBack:
2222         case WebFrameLoadTypeForward:
2223         case WebFrameLoadTypeIndexedBackForward:
2224         case WebFrameLoadTypeInternal:
2225         case WebFrameLoadTypeStandard:
2226             return [_private currentItem];
2227     }
2228     ASSERT_NOT_REACHED();
2229     return nil;
2230 }
2231
2232 // Walk the frame tree, telling all frames to save their form state into their current
2233 // history item.
2234 - (void)_saveDocumentAndScrollState
2235 {
2236     for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self]) {
2237         [[frame _bridge] saveDocumentState];
2238         [frame _saveScrollPositionAndViewStateToItem:[frame->_private currentItem]];
2239     }
2240 }
2241
2242 // Called after the FormsDelegate is done processing willSubmitForm:
2243 -(void)_continueAfterWillSubmitForm:(WebPolicyAction)policy
2244 {
2245     if (_private->listener) {
2246         [_private->listener _invalidate];
2247         [_private->listener release];
2248         _private->listener = nil;
2249     }
2250     [_private->provisionalDataSource _startLoading];
2251 }
2252
2253 -(void)_continueLoadRequestAfterNavigationPolicy:(NSURLRequest *)request formState:(WebFormState *)formState
2254 {
2255     // If we loaded an alternate page to replace an unreachableURL, we'll get in here with a
2256     // nil _private->policyDataSource because loading the alternate page will have passed
2257     // through this method already, nested; otherwise, _private->policyDataSource should still be set.
2258     ASSERT(_private->policyDataSource || [[self provisionalDataSource] unreachableURL] != nil);
2259
2260     WebHistoryItem *item = [_private provisionalItem];
2261
2262     // Two reasons we can't continue:
2263     //    1) Navigation policy delegate said we can't so request is nil. A primary case of this 
2264     //       is the user responding Cancel to the form repost nag sheet.
2265     //    2) User responded Cancel to an alert popped up by the before unload event handler.
2266     // The "before unload" event handler runs only for the main frame.
2267     BOOL canContinue = request && ([[self webView] mainFrame] != self || [_private->bridge shouldClose]);
2268
2269     if (!canContinue) {
2270         // If we were waiting for a quick redirect, but the policy delegate decided to ignore it, then we 
2271         // need to report that the client redirect was cancelled.
2272         if (_private->quickRedirectComing)
2273             [self _clientRedirectCancelledOrFinished:NO];
2274
2275         [self _setPolicyDataSource:nil];
2276         // If the navigation request came from the back/forward menu, and we punt on it, we have the 
2277         // problem that we have optimistically moved the b/f cursor already, so move it back.  For sanity, 
2278         // we only do this when punting a navigation for the target frame or top-level frame.  
2279         if (([item isTargetItem] || [[self webView] mainFrame] == self)
2280             && (_private->policyLoadType == WebFrameLoadTypeForward
2281                 || _private->policyLoadType == WebFrameLoadTypeBack
2282                 || _private->policyLoadType == WebFrameLoadTypeIndexedBackForward))
2283             [[[self webView] mainFrame] _resetBackForwardList];
2284         return;
2285     }
2286     
2287     WebFrameLoadType loadType = _private->policyLoadType;
2288     WebDataSource *dataSource = [_private->policyDataSource retain];
2289     
2290     [self stopLoading];
2291     [self _setLoadType:loadType];
2292     [self _setProvisionalDataSource:dataSource];
2293     [dataSource release];
2294
2295     [self _setPolicyDataSource:nil];
2296     
2297     // We tell the documentView provisionalDataSourceChanged:
2298     // once it has been created by the WebView.
2299     
2300     [self _setState: WebFrameStateProvisional];
2301     
2302     if (self == [[self webView] mainFrame])
2303         LOG(DocumentLoad, "loading %@", [[[self provisionalDataSource] request] URL]);
2304
2305     if ((loadType == WebFrameLoadTypeForward ||
2306         loadType == WebFrameLoadTypeBack ||
2307         loadType == WebFrameLoadTypeIndexedBackForward) &&
2308         [item hasPageCache]){
2309         NSDictionary *pageCache = [[_private provisionalItem] pageCache];
2310         if ([pageCache objectForKey:WebCorePageCacheStateKey]){
2311             LOG (PageCache, "Restoring page from back/forward cache, %@\n", [[_private provisionalItem] URL]);
2312             [_private->provisionalDataSource _loadFromPageCache:pageCache];
2313             return;
2314         }
2315     }
2316
2317     if (formState) {
2318         // It's a bit of a hack to reuse the WebPolicyDecisionListener for the continuation
2319         // mechanism across the willSubmitForm callout.
2320         _private->listener = [[WebPolicyDecisionListener alloc] _initWithTarget:self action:@selector(_continueAfterWillSubmitForm:)];
2321         [[[self webView] _formDelegate] frame:self sourceFrame:[formState sourceFrame] willSubmitForm:[formState form] withValues:[formState values] submissionListener:_private->listener];
2322     } 
2323     else {
2324         [self _continueAfterWillSubmitForm:WebPolicyUse];
2325     }
2326 }
2327
2328 - (void)_loadDataSource:(WebDataSource *)newDataSource withLoadType:(WebFrameLoadType)loadType formState:(WebFormState *)formState
2329 {
2330     ASSERT([self webView] != nil);
2331
2332     // Unfortunately the view must be non-nil, this is ultimately due
2333     // to KDE parser requiring a KHTMLView.  Once we settle on a final
2334     // KDE drop we should fix this dependency.
2335
2336     ASSERT([self frameView] != nil);
2337
2338     _private->policyLoadType = loadType;
2339
2340     WebFrame *parentFrame = [self parentFrame];
2341     if (parentFrame)
2342         [newDataSource _setOverrideEncoding:[[parentFrame dataSource] _overrideEncoding]];
2343     [newDataSource _setWebFrame:self];
2344
2345     [self _invalidatePendingPolicyDecisionCallingDefaultAction:YES];
2346
2347     [self _setPolicyDataSource:newDataSource];
2348
2349     [self _checkNavigationPolicyForRequest:[newDataSource request]
2350                                 dataSource:newDataSource
2351                                  formState:formState
2352                                    andCall:self
2353                               withSelector:@selector(_continueLoadRequestAfterNavigationPolicy:formState:)];
2354 }
2355
2356 - (void)_setProvisionalDataSource: (WebDataSource *)d
2357 {
2358     if (_private->provisionalDataSource != _private->dataSource) {
2359         [_private->provisionalDataSource _setWebFrame:nil];
2360     }
2361     [_private setProvisionalDataSource: d];
2362     [d _setWebFrame:self];
2363 }
2364
2365 // used to decide to use loadType=Same
2366 - (BOOL)_shouldTreatURLAsSameAsCurrent:(NSURL *)URL
2367 {
2368     WebHistoryItem *item = [_private currentItem];
2369     NSString* URLString = [URL _web_originalDataAsString];
2370     return [URLString isEqual:[item URLString]] || [URLString isEqual:[item originalURLString]];
2371 }    
2372
2373 - (void)_loadRequest:(NSURLRequest *)request inFrameNamed:(NSString *)frameName
2374 {
2375     if (frameName == nil) {
2376         [self loadRequest:request];
2377         return;
2378     }
2379
2380     WebFrame *frame = [self findFrameNamed:frameName];
2381     
2382     if (frame != nil) {
2383         [frame loadRequest:request];
2384         return;
2385     }
2386
2387     NSDictionary *action = [self _actionInformationForNavigationType:WebNavigationTypeOther event:nil originalURL:[request URL]];
2388     [self _checkNewWindowPolicyForRequest:request action:(NSDictionary *)action frameName:frameName formState:nil andCall:self withSelector:@selector(_continueLoadRequestAfterNewWindowPolicy:frameName:formState:)];
2389 }
2390
2391 // Return next frame to be traversed, visiting children after parent
2392 - (WebFrame *)_nextFrameWithWrap:(BOOL)wrapFlag
2393 {
2394     return Frame([[self _bridge] nextFrameWithWrap:wrapFlag]);
2395 }
2396
2397 // Return previous frame to be traversed, exact reverse order of _nextFrame
2398 - (WebFrame *)_previousFrameWithWrap:(BOOL)wrapFlag
2399 {
2400     return Frame([[self _bridge] previousFrameWithWrap:wrapFlag]);
2401 }
2402
2403 - (void)_setShouldCreateRenderers:(BOOL)f
2404 {
2405     [_private->bridge setShouldCreateRenderers:f];
2406 }
2407
2408 - (BOOL)_shouldCreateRenderers
2409 {
2410     return [_private->bridge shouldCreateRenderers];
2411 }
2412
2413 - (int)_numPendingOrLoadingRequests:(BOOL)recurse
2414 {
2415     if (!recurse)
2416         return [[self _bridge] numPendingOrLoadingRequests];
2417
2418     int num = 0;
2419     for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self])
2420         num += [[frame _bridge] numPendingOrLoadingRequests];
2421
2422     return num;
2423 }
2424
2425 - (NSColor *)_bodyBackgroundColor
2426 {
2427     return [_private->bridge bodyBackgroundColor];
2428 }
2429
2430 - (void)_reloadForPluginChanges
2431 {
2432     for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self]) {
2433         NSView <WebDocumentView> *documentView = [[frame frameView] documentView];
2434         if ([documentView isKindOfClass:[WebNetscapePluginDocumentView class]] ||
2435             [documentView isKindOfClass:[WebPluginDocumentView class]]) {
2436             [frame reload];
2437         } else if ([documentView isKindOfClass:[WebHTMLView class]]) {
2438             NSEnumerator *viewEnumerator = [[documentView subviews] objectEnumerator];
2439             NSView *view;
2440             // FIXME:  We should ask the frame if it contains plugins, rather
2441             // than doing this check.
2442             while ((view = [viewEnumerator nextObject]) != nil) {
2443                 if ([view isKindOfClass:[WebNetscapePluginEmbeddedView class]] ||
2444                     [view isKindOfClass:[WebNullPluginView class]] ||
2445                     [WebPluginController isPlugInView:view]) {
2446                     [frame reload];
2447                     break;
2448                 }
2449             }
2450         }
2451     }
2452 }
2453
2454 - (void)_attachScriptDebugger
2455 {
2456     if (!_private->scriptDebugger) {
2457         _private->scriptDebugger = [[WebScriptDebugger alloc] initWithWebFrame:self];
2458     }
2459 }
2460
2461 - (void)_recursive_pauseNullEventsForAllNetscapePlugins
2462 {
2463     for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self]) {
2464         NSView <WebDocumentView> *documentView = [[frame frameView] documentView];
2465         // FIXME: what about plugin document view?
2466         if ([documentView isKindOfClass:[WebHTMLView class]])
2467             [(WebHTMLView *)documentView _pauseNullEventsForAllNetscapePlugins];
2468     }
2469 }
2470
2471 - (void)_recursive_resumeNullEventsForAllNetscapePlugins
2472 {
2473     for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self]) {
2474         // FIXME: what about plugin document view?
2475         NSView <WebDocumentView> *documentView = [[frame frameView] documentView];
2476         if ([documentView isKindOfClass:[WebHTMLView class]])
2477             [(WebHTMLView *)documentView _resumeNullEventsForAllNetscapePlugins];
2478     }
2479 }
2480
2481 - (BOOL)_firstLayoutDone
2482 {
2483     return _private->firstLayoutDone;
2484 }
2485
2486 @end
2487
2488 @implementation WebFrame (WebInternal)
2489
2490 - (id)_initWithWebFrameView:(WebFrameView *)fv webView:(WebView *)v bridge:(WebFrameBridge *)bridge
2491 {
2492     self = [super init];
2493     if (!self)
2494         return nil;
2495
2496     _private = [[WebFramePrivate alloc] init];
2497
2498     _private->bridge = bridge;
2499
2500     if (fv) {
2501         [_private setWebFrameView:fv];
2502         [fv _setWebFrame:self];
2503     }
2504     
2505     ++WebFrameCount;
2506     
2507     return self;
2508 }
2509
2510 - (NSArray *)_documentViews
2511 {
2512     NSMutableArray *result = [NSMutableArray array];
2513     for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self]) {
2514         id docView = [[frame frameView] documentView];
2515         if (docView)
2516             [result addObject:docView];
2517     }
2518         
2519     return result;
2520 }
2521
2522 - (void)_updateDrawsBackground
2523 {
2524     BOOL drawsBackground = [[self webView] drawsBackground];
2525
2526     for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self]) {
2527         // FIXME: why not the other way for scroll view?
2528         if (!drawsBackground)
2529             [[[frame frameView] _scrollView] setDrawsBackground:NO];
2530         id documentView = [[frame frameView] documentView];
2531         if ([documentView respondsToSelector:@selector(setDrawsBackground:)])
2532             [documentView setDrawsBackground:drawsBackground];
2533         [[frame _bridge] setDrawsBackground:drawsBackground];
2534     }
2535 }
2536
2537 - (void)_setInternalLoadDelegate:(id)internalLoadDelegate
2538 {
2539     _private->internalLoadDelegate = internalLoadDelegate;
2540 }
2541
2542 - (id)_internalLoadDelegate
2543 {
2544     return _private->internalLoadDelegate;
2545 }
2546
2547 - (NSURLRequest *)_requestFromDelegateForRequest:(NSURLRequest *)request identifier:(id *)identifier error:(NSError **)error
2548 {
2549     ASSERT(request != nil);
2550     
2551     WebView *wv = [self webView];
2552     id delegate = [wv resourceLoadDelegate];
2553     id sharedDelegate = [WebDefaultResourceLoadDelegate sharedResourceLoadDelegate];
2554     WebResourceDelegateImplementationCache implementations = [wv _resourceLoadDelegateImplementations];
2555     WebDataSource *dataSource = [self dataSource];
2556     
2557     if (implementations.delegateImplementsIdentifierForRequest) {
2558         *identifier = [delegate webView:wv identifierForInitialRequest:request fromDataSource:dataSource];
2559     } else {
2560         *identifier = [sharedDelegate webView:wv identifierForInitialRequest:request fromDataSource:dataSource];
2561     }
2562         
2563     NSURLRequest *newRequest;
2564     if (implementations.delegateImplementsWillSendRequest) {
2565         newRequest = [delegate webView:wv resource:*identifier willSendRequest:request redirectResponse:nil fromDataSource:dataSource];
2566     } else {
2567         newRequest = [sharedDelegate webView:wv resource:*identifier willSendRequest:request redirectResponse:nil fromDataSource:dataSource];
2568     }
2569     
2570     if (newRequest == nil) {
2571         *error = [NSError _webKitErrorWithDomain:NSURLErrorDomain code:NSURLErrorCancelled URL:[request URL]];
2572     } else {
2573         *error = nil;
2574     }
2575     
2576     return newRequest;
2577 }
2578
2579 - (void)_sendRemainingDelegateMessagesWithIdentifier:(id)identifier response:(NSURLResponse *)response length:(unsigned)length error:(NSError *)error 
2580 {    
2581     WebView *wv = [self webView];
2582     id delegate = [wv resourceLoadDelegate];
2583     id sharedDelegate = [WebDefaultResourceLoadDelegate sharedResourceLoadDelegate];
2584     WebResourceDelegateImplementationCache implementations = [wv _resourceLoadDelegateImplementations];
2585     WebDataSource *dataSource = [self dataSource];
2586         
2587     if (response != nil) {
2588         if (implementations.delegateImplementsDidReceiveResponse) {
2589             [delegate webView:wv resource:identifier didReceiveResponse:response fromDataSource:dataSource];
2590         } else {
2591             [sharedDelegate webView:wv resource:identifier didReceiveResponse:response fromDataSource:dataSource];
2592         }
2593     }
2594     
2595     if (length > 0) {
2596         if (implementations.delegateImplementsDidReceiveContentLength) {
2597             [delegate webView:wv resource:identifier didReceiveContentLength:(WebNSUInt)length fromDataSource:dataSource];
2598         } else {
2599             [sharedDelegate webView:wv resource:identifier didReceiveContentLength:(WebNSUInt)length fromDataSource:dataSource];
2600         }
2601     }
2602     
2603     if (error == nil) {
2604         if (implementations.delegateImplementsDidFinishLoadingFromDataSource) {
2605             [delegate webView:wv resource:identifier didFinishLoadingFromDataSource:dataSource];
2606         } else {
2607             [sharedDelegate webView:wv resource:identifier didFinishLoadingFromDataSource:dataSource];
2608         }
2609         [wv _finishedLoadingResourceFromDataSource:dataSource];
2610     } else {
2611         [[wv _resourceLoadDelegateForwarder] webView:wv resource:identifier didFailLoadingWithError:error fromDataSource:dataSource];
2612     }
2613 }
2614
2615 - (void)_safeLoadURL:(NSURL *)URL
2616 {
2617    // Call the bridge because this is where our security checks are made.
2618     [[self _bridge] loadURL:URL 
2619                     referrer:[[[[self dataSource] request] URL] _web_originalDataAsString]
2620                       reload:NO
2621                  userGesture:YES       
2622                       target:nil
2623              triggeringEvent:[NSApp currentEvent]
2624                         form:nil 
2625                   formValues:nil];
2626 }
2627
2628 - (void)_saveResourceAndSendRemainingDelegateMessagesWithRequest:(NSURLRequest *)request
2629                                                       identifier:(id)identifier 
2630                                                         response:(NSURLResponse *)response 
2631                                                             data:(NSData *)data
2632                                                            error:(NSError *)error
2633 {
2634     unsigned length = [data length];
2635     if (length > 0 && error == nil) {
2636         ASSERT(request != nil);
2637         WebResource *resource = [[WebResource alloc] _initWithData:data URL:[request URL] response:response];
2638         ASSERT(resource != nil);    
2639         [[self dataSource] addSubresource:resource];
2640         [resource release];
2641     }
2642     [self _sendRemainingDelegateMessagesWithIdentifier:identifier response:response length:length error:error];
2643 }
2644
2645 - (void)_unmarkAllMisspellings
2646 {
2647     for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self])
2648         [[frame _bridge] unmarkAllMisspellings];
2649 }
2650
2651 - (void)_didFirstLayout
2652 {
2653     if ([[self webView] backForwardList]) {
2654         WebFrameLoadType loadType = [self _loadType];
2655         if (loadType == WebFrameLoadTypeForward ||
2656             loadType == WebFrameLoadTypeBack ||
2657             loadType == WebFrameLoadTypeIndexedBackForward)
2658         {
2659             [self _restoreScrollPositionAndViewState];
2660         }
2661     }
2662     
2663     _private->firstLayoutDone = YES;
2664 }
2665
2666 - (void)_setupForReplace
2667 {
2668     [self _setState:WebFrameStateProvisional];
2669     WebDataSource *old = _private->provisionalDataSource;
2670     _private->provisionalDataSource = _private->dataSource;
2671     _private->dataSource = nil;
2672     [old release];
2673         
2674     [self _detachChildren];
2675 }
2676
2677 - (BOOL)_hasSelection
2678 {
2679     id documentView = [[self frameView] documentView];    
2680     
2681     // optimization for common case to avoid creating potentially large selection string
2682     if ([documentView isKindOfClass:[WebHTMLView class]]) {
2683         DOMRange *selectedDOMRange = [[self _bridge] selectedDOMRange];
2684         return selectedDOMRange && ![selectedDOMRange collapsed];
2685     }
2686     
2687     if ([documentView conformsToProtocol:@protocol(WebDocumentText)])
2688         return [[documentView selectedString] length] > 0;
2689     
2690     return NO;
2691 }
2692
2693 - (void)_clearSelection
2694 {
2695     id documentView = [[self frameView] documentView];    
2696     if ([documentView conformsToProtocol:@protocol(WebDocumentText)])
2697         [documentView deselectAll];
2698 }
2699
2700 #ifndef NDEBUG
2701
2702 - (BOOL)_atMostOneFrameHasSelection;
2703 {
2704     // FIXME: 4186050 is one known case that makes this debug check fail
2705     BOOL found = NO;
2706     for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self]) {
2707         if ([frame _hasSelection]) {
2708             if (found)
2709                 return NO;
2710             found = YES;
2711         }
2712     }
2713
2714     return YES;
2715 }
2716 #endif
2717
2718 - (WebFrame *)_findFrameWithSelection
2719 {
2720     ASSERT([self _atMostOneFrameHasSelection]);
2721
2722     for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self])
2723         if ([frame _hasSelection])
2724             return frame;
2725
2726     return nil;
2727 }
2728
2729 - (void)_clearSelectionInOtherFrames
2730 {
2731     // We rely on WebDocumentSelection protocol implementors to call this method when they become first 
2732     // responder. It would be nicer to just notice first responder changes here instead, but there's no 
2733     // notification sent when the first responder changes in general (Radar 2573089).
2734     WebFrame *frameWithSelection = [[[self webView] mainFrame] _findFrameWithSelection];
2735     if (frameWithSelection != self)
2736         [frameWithSelection _clearSelection];
2737
2738     // While we're in the general area of selection and frames, check that there is only one now.
2739     ASSERT([[[self webView] mainFrame] _atMostOneFrameHasSelection]);
2740 }
2741
2742 - (void)_stopLoadingSubframes
2743 {
2744     for (WebFrame *child = [self _firstChildFrame]; child; child = [child _nextSiblingFrame])
2745         [child stopLoading];
2746 }
2747
2748 - (BOOL)_subframeIsLoading
2749 {
2750     // Put in the auto-release pool because it's common to call this from a run loop source,
2751     // and then the entire list of frames lasts until the next autorelease.
2752     // FIXME: is this really still true? we use _firstChildFrame/_nextSiblingFrame now 
2753     // which does not make a copy.
2754     NSAutoreleasePool *pool = [NSAutoreleasePool new];
2755
2756     WebFrame *frame;
2757     for (frame = [self _firstChildFrame]; frame; frame = [frame _nextSiblingFrame])
2758         if ([[frame dataSource] isLoading] || [[frame provisionalDataSource] isLoading])
2759             break;
2760
2761     [pool drain];
2762     
2763     return frame != nil;
2764 }
2765
2766 @end
2767
2768 @implementation WebFormState : NSObject
2769
2770 - (id)initWithForm:(DOMElement *)form values:(NSDictionary *)values sourceFrame:(WebFrame *)sourceFrame
2771 {
2772     self = [super init];
2773     if (!self)
2774         return nil;
2775     
2776     _form = [form retain];
2777     _values = [values copy];
2778     _sourceFrame = [sourceFrame retain];
2779     return self;
2780 }
2781
2782 - (void)dealloc
2783 {
2784     [_form release];
2785     [_values release];
2786     [_sourceFrame release];
2787     [super dealloc];
2788 }
2789
2790 - (DOMElement *)form
2791 {
2792     return _form;
2793 }
2794
2795 - (NSDictionary *)values
2796 {
2797     return _values;
2798 }
2799
2800 - (WebFrame *)sourceFrame
2801 {
2802     return _sourceFrame;
2803 }
2804
2805 @end
2806
2807 @implementation WebFrame
2808
2809 - (id)init
2810 {
2811     return [self initWithName:nil webFrameView:nil webView:nil];
2812 }
2813
2814 // FIXME: this method can't work any more and should be marked deprecated
2815 - (id)initWithName:(NSString *)n webFrameView:(WebFrameView *)fv webView:(WebView *)v
2816 {
2817     return [self _initWithWebFrameView:fv webView:v bridge:nil];
2818 }
2819
2820 - (void)dealloc
2821 {
2822     [self _detachFromParent];
2823     [_private release];
2824
2825     --WebFrameCount;
2826
2827     [super dealloc];
2828 }
2829
2830 - (void)finalize
2831 {
2832     // FIXME: Should not do this work at finalize time. Need to do it at a predictable time instead.
2833     [self _detachFromParent];
2834     --WebFrameCount;
2835
2836     [super finalize];
2837 }
2838
2839 - (NSString *)name
2840 {
2841     return [[self _bridge] name];
2842 }
2843
2844 - (WebFrameView *)frameView
2845 {
2846     return [_private webFrameView];
2847 }
2848
2849 - (WebView *)webView
2850 {
2851     return [[[self _bridge] page] webView];
2852 }
2853
2854 - (DOMDocument *)DOMDocument
2855 {
2856     return [[self dataSource] _isDocumentHTML] ? [_private->bridge DOMDocument] : nil;
2857 }
2858
2859 - (DOMHTMLElement *)frameElement
2860 {
2861     return [[self webView] mainFrame] != self ? [_private->bridge frameElement] : nil;
2862 }
2863
2864 - (WebDataSource *)provisionalDataSource
2865 {
2866     return [_private provisionalDataSource];
2867 }
2868
2869 - (WebDataSource *)dataSource
2870 {
2871     return [_private dataSource];
2872 }
2873
2874 - (void)loadRequest:(NSURLRequest *)request
2875 {
2876     [self _loadRequest:request subresources:nil subframeArchives:nil];
2877 }
2878
2879 - (void)_loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)URL unreachableURL:(NSURL *)unreachableURL
2880 {
2881     NSURLRequest *request = [self _webDataRequestForData:data 
2882                                                 MIMEType:MIMEType 
2883                                         textEncodingName:encodingName 
2884                                                  baseURL:URL
2885                                           unreachableURL:unreachableURL];
2886     [self loadRequest:request];
2887 }
2888
2889
2890 - (void)loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)URL
2891 {
2892     [self _loadData:data MIMEType:MIMEType textEncodingName:encodingName baseURL:URL unreachableURL:nil];
2893 }
2894
2895 - (void)_loadHTMLString:(NSString *)string baseURL:(NSURL *)URL unreachableURL:(NSURL *)unreachableURL
2896 {
2897     CFStringEncoding cfencoding = CFStringGetFastestEncoding((CFStringRef)string);
2898     NSStringEncoding nsencoding = CFStringConvertEncodingToNSStringEncoding(cfencoding);
2899     CFStringRef cfencodingName = CFStringConvertEncodingToIANACharSetName(cfencoding);
2900     
2901     if (!cfencodingName || nsencoding == kCFStringEncodingInvalidId){
2902         NSData *data = [string dataUsingEncoding: NSUnicodeStringEncoding];
2903         [self _loadData:data MIMEType:nil textEncodingName:@"utf-16" baseURL:URL unreachableURL:unreachableURL];
2904     }
2905     else {
2906         NSData *data = [string dataUsingEncoding: nsencoding];
2907         [self _loadData:data MIMEType:nil textEncodingName:(NSString *)cfencodingName baseURL:URL unreachableURL:unreachableURL];
2908     }
2909 }
2910
2911 - (void)loadHTMLString:(NSString *)string baseURL:(NSURL *)URL
2912 {
2913     [self _loadHTMLString:string baseURL:URL unreachableURL:nil];
2914 }
2915
2916 - (void)loadAlternateHTMLString:(NSString *)string baseURL:(NSURL *)URL forUnreachableURL:(NSURL *)unreachableURL
2917 {
2918     [self _loadHTMLString:string baseURL:URL unreachableURL:unreachableURL];
2919 }
2920
2921 - (void)loadArchive:(WebArchive *)archive
2922 {
2923     WebResource *mainResource = [archive mainResource];
2924     if (mainResource) {
2925         NSURLRequest *request = [self _webDataRequestForData:[mainResource data] 
2926                                                     MIMEType:[mainResource MIMEType]
2927                                             textEncodingName:[mainResource textEncodingName]
2928                                                      baseURL:[mainResource URL]
2929                                               unreachableURL:nil];
2930         [self _loadRequest:request subresources:[archive subresources] subframeArchives:[archive subframeArchives]];
2931     }
2932 }
2933
2934 - (void)stopLoading
2935 {
2936     // If this method is called from within this method, infinite recursion can occur (3442218). Avoid this.
2937     if (_private->isStoppingLoad)
2938         return;
2939
2940     _private->isStoppingLoad = YES;
2941     
2942     [self _invalidatePendingPolicyDecisionCallingDefaultAction:YES];
2943
2944     [self _stopLoadingSubframes];
2945     [_private->provisionalDataSource _stopLoading];
2946     [_private->dataSource _stopLoading];
2947
2948     [self _setProvisionalDataSource:nil];
2949
2950     _private->isStoppingLoad = NO;
2951 }
2952
2953 - (void)reload
2954 {
2955     WebDataSource *dataSource = [self dataSource];
2956     if (dataSource == nil)
2957         return;
2958
2959     NSMutableURLRequest *initialRequest = [dataSource request];
2960     
2961     // If a window is created by javascript, its main frame can have an empty but non-nil URL.
2962     // Reloading in this case will lose the current contents (see 4151001).
2963     if ([[[[dataSource request] URL] absoluteString] length] == 0) {
2964         return;
2965     }
2966
2967     // Replace error-page URL with the URL we were trying to reach.
2968     NSURL *unreachableURL = [initialRequest _webDataRequestUnreachableURL];
2969     if (unreachableURL != nil) {
2970         initialRequest = [NSURLRequest requestWithURL:unreachableURL];
2971     }
2972     
2973     // initWithRequest copies the request
2974     WebDataSource *newDataSource = [[WebDataSource alloc] initWithRequest:initialRequest];
2975     NSMutableURLRequest *request = [newDataSource request];
2976
2977     [request setCachePolicy:NSURLRequestReloadIgnoringCacheData];
2978
2979     // If we're about to rePOST, set up action so the app can warn the user
2980     if ([[request HTTPMethod] _webkit_isCaseInsensitiveEqualToString:@"POST"]) {
2981         NSDictionary *action = [self _actionInformationForNavigationType:WebNavigationTypeFormResubmitted event:nil originalURL:[request URL]];
2982         [newDataSource _setTriggeringAction:action];
2983     }
2984
2985     [newDataSource _setOverrideEncoding:[dataSource _overrideEncoding]];
2986     
2987     [self _loadDataSource:newDataSource withLoadType:WebFrameLoadTypeReload formState:nil];
2988
2989     [newDataSource release];
2990 }
2991
2992 - (WebFrame *)findFrameNamed:(NSString *)name
2993 {
2994     return Frame([[self _bridge] findFrameNamed:name]);
2995 }
2996
2997 - (WebFrame *)parentFrame
2998 {
2999     return [[Frame([[self _bridge] parent]) retain] autorelease];
3000 }
3001
3002 - (NSArray *)childFrames
3003 {
3004     NSMutableArray *children = [NSMutableArray arrayWithCapacity:[self _childFrameCount]];
3005     for (WebFrame *child = [self _firstChildFrame]; child; child = [child _nextSiblingFrame])
3006         [children addObject:child];
3007
3008     return children;
3009 }
3010
3011 @end