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