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