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