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