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