Reviewed by Maciej.
[WebKit-https.git] / WebKit / WebView / WebFrame.m
1 /*
2  * Copyright (C) 2005, 2006 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 "WebFrameInternal.h"
30
31 #import "WebArchive.h"
32 #import "WebBackForwardList.h"
33 #import "WebDataProtocol.h"
34 #import "WebDataSourceInternal.h"
35 #import "WebDefaultResourceLoadDelegate.h"
36 #import "WebDefaultUIDelegate.h"
37 #import "WebDocumentInternal.h"
38 #import "WebDocumentLoaderMac.h"
39 #import "WebDownloadInternal.h"
40 #import "WebFormDataStream.h"
41 #import "WebFrameBridge.h"
42 #import "WebFrameLoadDelegate.h"
43 #import "WebFrameLoader.h"
44 #import "WebFrameViewInternal.h"
45 #import "WebHTMLRepresentationPrivate.h"
46 #import "WebHTMLViewInternal.h"
47 #import "WebHTMLViewPrivate.h"
48 #import "WebHistoryItemPrivate.h"
49 #import "WebHistoryPrivate.h"
50 #import "WebKitErrorsPrivate.h"
51 #import "WebKitLogging.h"
52 #import "WebKitNSStringExtras.h"
53 #import "WebKitStatisticsPrivate.h"
54 #import "WebNSObjectExtras.h"
55 #import "WebNSURLExtras.h"
56 #import "WebNSURLRequestExtras.h"
57 #import "WebNetscapePluginEmbeddedView.h"
58 #import "WebNullPluginView.h"
59 #import "WebPlugin.h"
60 #import "WebPluginController.h"
61 #import "WebPreferencesPrivate.h"
62 #import "WebResourceLoadDelegate.h"
63 #import "WebResourcePrivate.h"
64 #import "WebScriptDebugDelegatePrivate.h"
65 #import "WebUIDelegate.h"
66 #import "WebViewInternal.h"
67 #import <WebKit/DOM.h>
68 #import <WebKitSystemInterface.h>
69 #import <objc/objc-runtime.h>
70
71 /*
72 Here is the current behavior matrix for four types of navigations:
73
74 Standard Nav:
75
76  Restore form state:   YES
77  Restore scroll and focus state:  YES
78  WF Cache policy: NSURLRequestUseProtocolCachePolicy
79  Add to back/forward list: YES
80  
81 Back/Forward:
82
83  Restore form state:   YES
84  Restore scroll and focus state:  YES
85  WF Cache policy: NSURLRequestReturnCacheDataElseLoad
86  Add to back/forward list: NO
87
88 Reload (meaning only the reload button):
89
90  Restore form state:   NO
91  Restore scroll and focus state:  YES
92  WF Cache policy: NSURLRequestReloadIgnoringCacheData
93  Add to back/forward list: NO
94
95 Repeat load of the same URL (by any other means of navigation other than the reload button, including hitting return in the location field):
96
97  Restore form state:   NO
98  Restore scroll and focus state:  NO, reset to initial conditions
99  WF Cache policy: NSURLRequestReloadIgnoringCacheData
100  Add to back/forward list: NO
101 */
102
103 NSString *WebPageCacheEntryDateKey = @"WebPageCacheEntryDateKey";
104 NSString *WebPageCacheDataSourceKey = @"WebPageCacheDataSourceKey";
105 NSString *WebPageCacheDocumentViewKey = @"WebPageCacheDocumentViewKey";
106
107 @interface WebFrame (ForwardDecls)
108 - (void)_loadHTMLString:(NSString *)string baseURL:(NSURL *)URL unreachableURL:(NSURL *)unreachableURL;
109 - (void)_saveScrollPositionAndViewStateToItem:(WebHistoryItem *)item;
110 - (WebHistoryItem *)_createItem:(BOOL)useOriginal;
111 - (WebHistoryItem *)_createItemTreeWithTargetFrame:(WebFrame *)targetFrame clippedAtTarget:(BOOL)doClip;
112 - (WebHistoryItem *)_currentBackForwardListItemToResetTo;
113 @end
114
115 @interface NSView (WebFramePluginHosting)
116 - (void)setWebFrame:(WebFrame *)webFrame;
117 @end
118
119 @interface WebFramePrivate : NSObject
120 {
121 @public
122     WebFrameView *webFrameView;
123
124     WebFrameBridge *bridge;
125     WebHistoryItem *currentItem;        // BF item for our current content
126     WebHistoryItem *provisionalItem;    // BF item for where we're trying to go
127                                         // (only known when navigating to a pre-existing BF item)
128     WebHistoryItem *previousItem;       // BF item for previous content, see _itemForSavingDocState
129
130     WebScriptDebugger *scriptDebugger;
131     id internalLoadDelegate;
132     
133     NSMutableSet *plugInViews;
134     NSMutableSet *inspectors;
135 }
136
137 - (void)setWebFrameView:(WebFrameView *)v;
138
139 - (void)setProvisionalItem:(WebHistoryItem *)item;
140 - (void)setPreviousItem:(WebHistoryItem *)item;
141 - (void)setCurrentItem:(WebHistoryItem *)item;
142
143 @end
144
145 @implementation WebFramePrivate
146
147 - (void)dealloc
148 {
149     [webFrameView release];
150
151     [currentItem release];
152     [provisionalItem release];
153     [previousItem release];
154     
155     [scriptDebugger release];
156     
157     [inspectors release];
158
159     ASSERT(plugInViews == nil);
160     
161     [super dealloc];
162 }
163
164 - (void)setWebFrameView:(WebFrameView *)v 
165
166     [v retain];
167     [webFrameView release];
168     webFrameView = v;
169 }
170
171 - (void)setProvisionalItem:(WebHistoryItem *)item
172 {
173     [item retain];
174     [provisionalItem release];
175     provisionalItem = item;
176 }
177
178 - (void)setPreviousItem:(WebHistoryItem *)item
179 {
180     [item retain];
181     [previousItem release];
182     previousItem = item;
183 }
184
185 - (void)setCurrentItem:(WebHistoryItem *)item
186 {
187     [item retain];
188     [currentItem release];
189     currentItem = item;
190 }
191
192 @end
193
194 static inline WebFrame *Frame(WebCoreFrameBridge *bridge)
195 {
196     return [(WebFrameBridge *)bridge webFrame];
197 }
198
199 @implementation WebFrame (FrameTraversal)
200
201 - (WebFrame *)_firstChildFrame
202 {
203     return Frame([[self _bridge] firstChild]);
204 }
205
206 - (WebFrame *)_lastChildFrame
207 {
208     return Frame([[self _bridge] lastChild]);
209 }
210
211 - (unsigned)_childFrameCount
212 {
213     return [[self _bridge] childCount];
214 }
215
216 - (WebFrame *)_previousSiblingFrame;
217 {
218     return Frame([[self _bridge] previousSibling]);
219 }
220
221 - (WebFrame *)_nextSiblingFrame;
222 {
223     return Frame([[self _bridge] nextSibling]);
224 }
225
226 - (WebFrame *)_traverseNextFrameStayWithin:(WebFrame *)stayWithin
227 {
228     return Frame([[self _bridge] traverseNextFrameStayWithin:[stayWithin _bridge]]);
229 }
230
231 @end
232
233 @implementation WebFrame (WebInternal)
234
235 - (NSURLRequest *)_webDataRequestForData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)URL unreachableURL:(NSURL *)unreachableURL
236 {
237     NSURL *fakeURL = [NSURL _web_uniqueWebDataURL];
238     NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] initWithURL:fakeURL] autorelease];
239     [request _webDataRequestSetData:data];
240     [request _webDataRequestSetEncoding:encodingName];
241     [request _webDataRequestSetBaseURL:URL];
242     [request _webDataRequestSetUnreachableURL:unreachableURL];
243     [request _webDataRequestSetMIMEType: MIMEType ? MIMEType : (NSString *)@"text/html"];
244     return request;
245 }
246
247 // helper method used in various nav cases below
248 - (void)_addBackForwardItemClippedAtTarget:(BOOL)doClip
249 {
250     if ([[self dataSource] _URLForHistory] != nil) {
251         WebHistoryItem *bfItem = [[[self webView] mainFrame] _createItemTreeWithTargetFrame:self clippedAtTarget:doClip];
252         LOG (BackForward, "for frame %@, adding item  %@\n", [self name], bfItem);
253         [[[self webView] backForwardList] addItem:bfItem];
254     }
255 }
256
257 - (void)_addHistoryItemForFragmentScroll
258 {
259     [self _addBackForwardItemClippedAtTarget:NO];
260 }
261
262 - (void)_didFinishLoad
263 {
264     [_private->internalLoadDelegate webFrame:self didFinishLoadWithError:nil];    
265 }
266
267 - (WebHistoryItem *)_createItem:(BOOL)useOriginal
268 {
269     WebDataSource *dataSrc = [self dataSource];
270     NSURLRequest *request;
271     NSURL *unreachableURL = [dataSrc unreachableURL];
272     NSURL *URL;
273     NSURL *originalURL;
274     WebHistoryItem *bfItem;
275
276     if (useOriginal)
277         request = [[dataSrc _documentLoader] originalRequestCopy];
278     else
279         request = [dataSrc request];
280
281     if (unreachableURL != nil) {
282         URL = unreachableURL;
283         originalURL = unreachableURL;
284     } else {
285         URL = [request URL];
286         originalURL = [[[dataSrc _documentLoader] originalRequestCopy] URL];
287     }
288
289     LOG (History, "creating item for %@", request);
290     
291     // Frames that have never successfully loaded any content
292     // may have no URL at all. Currently our history code can't
293     // deal with such things, so we nip that in the bud here.
294     // Later we may want to learn to live with nil for URL.
295     // See bug 3368236 and related bugs for more information.
296     if (URL == nil) {
297         URL = [NSURL URLWithString:@"about:blank"];
298     }
299     if (originalURL == nil) {
300         originalURL = [NSURL URLWithString:@"about:blank"];
301     }
302     
303     bfItem = [[[WebHistoryItem alloc] initWithURL:URL target:[self name] parent:[[self parentFrame] name] title:[dataSrc pageTitle]] autorelease];
304     [bfItem setOriginalURLString:[originalURL _web_originalDataAsString]];
305
306     // save form state if this is a POST
307     [bfItem _setFormInfoFromRequest:request];
308
309     // Set the item for which we will save document state
310     [_private setPreviousItem:_private->currentItem];
311     [_private setCurrentItem:bfItem];
312
313     return bfItem;
314 }
315
316 /*
317     In the case of saving state about a page with frames, we store a tree of items that mirrors the frame tree.  
318     The item that was the target of the user's navigation is designated as the "targetItem".  
319     When this method is called with doClip=YES we're able to create the whole tree except for the target's children, 
320     which will be loaded in the future.  That part of the tree will be filled out as the child loads are committed.
321 */
322 - (WebHistoryItem *)_createItemTreeWithTargetFrame:(WebFrame *)targetFrame clippedAtTarget:(BOOL)doClip
323 {
324     WebHistoryItem *bfItem = [self _createItem:[self parentFrame] ? YES : NO];
325
326     [self _saveScrollPositionAndViewStateToItem:_private->previousItem];
327     if (!(doClip && self == targetFrame)) {
328         // save frame state for items that aren't loading (khtml doesn't save those)
329         [_private->bridge saveDocumentState];
330
331         for (WebFrame *child = [self _firstChildFrame]; child; child = [child _nextSiblingFrame])
332             [bfItem addChildItem:[child _createItemTreeWithTargetFrame:targetFrame clippedAtTarget:doClip]];
333     }
334     if (self == targetFrame)
335         [bfItem setIsTargetItem:YES];
336
337     return bfItem;
338 }
339
340 - (WebFrame *)_immediateChildFrameNamed:(NSString *)name
341 {
342     return Frame([[self _bridge] childFrameNamed:name]);
343 }
344
345 - (BOOL)_canCachePage
346 {
347     return [[[self webView] backForwardList] _usesPageCache];
348 }
349
350 - (void)_purgePageCache
351 {
352     // This method implements the rule for purging the page cache.
353     unsigned sizeLimit = [[[self webView] backForwardList] pageCacheSize];
354     unsigned pagesCached = 0;
355     WebBackForwardList *backForwardList = [[self webView] backForwardList];
356     NSArray *backList = [backForwardList backListWithLimit: 999999];
357     WebHistoryItem *oldestNonSnapbackItem = nil;
358     
359     unsigned i;
360     for (i = 0; i < [backList count]; i++){
361         WebHistoryItem *item = [backList objectAtIndex: i];
362         if ([item hasPageCache]){
363             if (oldestNonSnapbackItem == nil && ![item alwaysAttemptToUsePageCache])
364                 oldestNonSnapbackItem = item;
365             pagesCached++;
366         }
367     }
368
369     // Snapback items are never directly purged here.
370     if (pagesCached >= sizeLimit) {
371         LOG(PageCache, "Purging back/forward cache, %@\n", [oldestNonSnapbackItem URL]);
372         [oldestNonSnapbackItem setHasPageCache:NO];
373     }
374 }
375
376 + (CFAbsoluteTime)_timeOfLastCompletedLoad
377 {
378     return [WebFrameLoader timeOfLastCompletedLoad];
379 }
380
381 - (BOOL)_createPageCacheForItem:(WebHistoryItem *)item
382 {
383     NSMutableDictionary *pageCache;
384
385     [item setHasPageCache: YES];
386
387     if (![_private->bridge saveDocumentToPageCache]){
388         [item setHasPageCache: NO];
389         return NO;
390     }
391     else {
392         pageCache = [item pageCache];
393         [pageCache setObject:[NSDate date]  forKey: WebPageCacheEntryDateKey];
394         [pageCache setObject:[self dataSource] forKey: WebPageCacheDataSourceKey];
395         [pageCache setObject:[[self frameView] documentView] forKey: WebPageCacheDocumentViewKey];
396     }
397     return YES;
398 }
399
400 - (void)_provisionalLoadStarted
401 {
402     FrameLoadType loadType = [[self _frameLoader] loadType];
403     
404     // FIXME: This is OK as long as no one resizes the window,
405     // but in the case where someone does, it means garbage outside
406     // the occupied part of the scroll view.
407     [[[self frameView] _scrollView] setDrawsBackground:NO];
408     
409     // Cache the page, if possible.
410     // Don't write to the cache if in the middle of a redirect, since we will want to
411     // store the final page we end up on.
412     // No point writing to the cache on a reload or loadSame, since we will just write
413     // over it again when we leave that page.
414     WebHistoryItem *item = _private->currentItem;
415     if ([self _canCachePage]
416         && [_private->bridge canCachePage]
417         && item
418         && ![[self _frameLoader] isQuickRedirectComing]
419         && loadType != FrameLoadTypeReload 
420         && loadType != FrameLoadTypeReloadAllowingStaleData
421         && loadType != FrameLoadTypeSame
422         && ![[self dataSource] isLoading]
423         && ![[[self _frameLoader] documentLoader] isStopping]) {
424         if ([[[self dataSource] representation] isKindOfClass:[WebHTMLRepresentation class]]) {
425             if (![item pageCache]){
426                 // Add the items to this page's cache.
427                 if ([self _createPageCacheForItem:item]) {
428                     LOG(PageCache, "Saving page to back/forward cache, %@\n", [[self dataSource] _URL]);
429                     
430                     // See if any page caches need to be purged after the addition of this
431                     // new page cache.
432                     [self _purgePageCache];
433                 }
434                 else
435                     LOG(PageCache, "NOT saving page to back/forward cache, unable to create items, %@\n", [[self dataSource] _URL]);
436             }
437         } else
438             // Put the document into a null state, so it can be restored correctly.
439             [_private->bridge clear];
440     } else
441         LOG(PageCache, "NOT saving page to back/forward cache, %@\n", [[self dataSource] _URL]);
442 }
443
444 - (WebFrameBridge *)_bridge
445 {
446     return _private->bridge;
447 }
448
449 // helper method that determines whether the subframes described by the item's subitems
450 // match our own current frameset
451 - (BOOL)_childFramesMatchItem:(WebHistoryItem *)item
452 {
453     NSArray *childItems = [item children];
454     int numChildItems = [childItems count];
455     int numChildFrames = [self _childFrameCount];
456     if (numChildFrames != numChildItems)
457         return NO;
458
459     int i;
460     for (i = 0; i < numChildItems; i++) {
461         NSString *itemTargetName = [[childItems objectAtIndex:i] target];
462         //Search recursive here?
463         if (![self _immediateChildFrameNamed:itemTargetName])
464             return NO; // couldn't match the i'th itemTarget
465     }
466
467     return YES; // found matches for all itemTargets
468 }
469
470 // Walk the frame tree and ensure that the URLs match the URLs in the item.
471 - (BOOL)_URLsMatchItem:(WebHistoryItem *)item
472 {
473     NSURL *currentURL = [[[self dataSource] request] URL];
474
475     if (![[[item URL] _webkit_URLByRemovingFragment] isEqual:[currentURL _webkit_URLByRemovingFragment]])
476         return NO;
477     
478     NSArray *childItems = [item children];
479     WebHistoryItem *childItem;
480     WebFrame *childFrame;
481     int i, count = [childItems count];
482     for (i = 0; i < count; i++){
483         childItem = [childItems objectAtIndex:i];
484         childFrame = [self _immediateChildFrameNamed:[childItem target]];
485         if (![childFrame _URLsMatchItem: childItem])
486             return NO;
487     }
488     
489     return YES;
490 }
491
492 // loads content into this frame, as specified by item
493 - (void)_loadItem:(WebHistoryItem *)item withLoadType:(FrameLoadType)loadType
494 {
495     NSURL *itemURL = [item URL];
496     NSURL *itemOriginalURL = [NSURL _web_URLWithDataAsString:[item originalURLString]];
497     NSURL *currentURL = [[[self dataSource] request] URL];
498     NSArray *formData = [item formData];
499
500     // Are we navigating to an anchor within the page?
501     // Note if we have child frames we do a real reload, since the child frames might not
502     // match our current frame structure, or they might not have the right content.  We could
503     // check for all that as an additional optimization.
504     // We also do not do anchor-style navigation if we're posting a form.
505     
506     // FIXME: These checks don't match the ones in _loadURL:referrer:loadType:target:triggeringEvent:isFormSubmission:
507     // Perhaps they should.
508     if (!formData && ![[self _frameLoader] shouldReloadForCurrent:itemURL andDestination:currentURL] && [self _URLsMatchItem:item] )
509     {
510 #if 0
511         // FIXME:  We need to normalize the code paths for anchor navigation.  Something
512         // like the following line of code should be done, but also accounting for correct
513         // updates to the back/forward list and scroll position.
514         // rjw 4/9/03 See 3223929.
515         [self _loadURL:itemURL referrer:[[[self dataSource] request] HTTPReferrer] loadType:loadType target:nil triggeringEvent:nil form:nil formValues:nil];
516 #endif
517         // must do this maintenance here, since we don't go through a real page reload
518         [self _saveScrollPositionAndViewStateToItem:_private->currentItem];
519         // FIXME: form state might want to be saved here too
520
521         // We always call scrollToAnchorWithURL here, even if the URL doesn't have an
522         // anchor fragment. This is so we'll keep the WebCore Frame's URL up-to-date.
523         [_private->bridge scrollToAnchorWithURL:[item URL]];
524     
525         // must do this maintenance here, since we don't go through a real page reload
526         [_private setCurrentItem:item];
527         [self _restoreScrollPositionAndViewState];
528
529         // Fake the URL change by updating the data source's request.  This will no longer
530         // be necessary if we do the better fix described above.
531         [[[self _frameLoader] documentLoader] replaceRequestURLForAnchorScrollWithURL:itemURL];
532         
533         [[[self webView] _frameLoadDelegateForwarder] webView:[self webView]
534                                didChangeLocationWithinPageForFrame:self];
535         [_private->internalLoadDelegate webFrame:self didFinishLoadWithError:nil];
536     } else {
537         // Remember this item so we can traverse any child items as child frames load
538         [_private setProvisionalItem:item];
539
540         WebDataSource *newDataSource;
541         BOOL inPageCache = NO;
542         
543         // Check if we'll be using the page cache.  We only use the page cache
544         // if one exists and it is less than _backForwardCacheExpirationInterval
545         // seconds old.  If the cache is expired it gets flushed here.
546         if ([item hasPageCache]){
547             NSDictionary *pageCache = [item pageCache];
548             NSDate *cacheDate = [pageCache objectForKey: WebPageCacheEntryDateKey];
549             NSTimeInterval delta = [[NSDate date] timeIntervalSinceDate: cacheDate];
550             if (delta <= [[[self webView] preferences] _backForwardCacheExpirationInterval]) {
551                 newDataSource = [pageCache objectForKey: WebPageCacheDataSourceKey];
552                 [[self _frameLoader] loadDataSource:newDataSource withLoadType:loadType formState:nil];   
553                 inPageCache = YES;
554             } else {
555                 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]);
556                 [item setHasPageCache: NO];
557             }
558         }
559         
560         if (!inPageCache) {
561             NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:itemURL];
562             [[self _frameLoader] addExtraFieldsToRequest:request mainResource:YES alwaysFromRequest:(formData != nil) ? YES : NO];
563
564             // If this was a repost that failed the page cache, we might try to repost the form.
565             NSDictionary *action;
566             if (formData) {
567                 [request setHTTPMethod:@"POST"];
568                 [request _web_setHTTPReferrer:[item formReferrer]];
569                 webSetHTTPBody(request, formData);
570                 [request _web_setHTTPContentType:[item formContentType]];
571
572                 // Slight hack to test if the WF cache contains the page we're going to.  We want
573                 // to know this before talking to the policy delegate, since it affects whether we
574                 // show the DoYouReallyWantToRepost nag.
575                 //
576                 // This trick has a small bug (3123893) where we might find a cache hit, but then
577                 // have the item vanish when we try to use it in the ensuing nav.  This should be
578                 // extremely rare, but in that case the user will get an error on the navigation.
579                 [request setCachePolicy:NSURLRequestReturnCacheDataDontLoad];
580                 NSURLResponse *synchResponse = nil;
581                 [NSURLConnection sendSynchronousRequest:request returningResponse:&synchResponse error:nil];
582                 if (synchResponse == nil) { 
583                     // Not in WF cache
584                     [request setCachePolicy:NSURLRequestReloadIgnoringCacheData];
585                     action = [[self _frameLoader] actionInformationForNavigationType:WebNavigationTypeFormResubmitted event:nil originalURL:itemURL];
586                 } else {
587                     // We can use the cache, don't use navType=resubmit
588                     action = [[self _frameLoader] actionInformationForLoadType:loadType isFormSubmission:NO event:nil originalURL:itemURL];
589                 }
590             } else {
591                 switch (loadType) {
592                     case FrameLoadTypeReload:
593                         [request setCachePolicy:NSURLRequestReloadIgnoringCacheData];
594                         break;
595                     case FrameLoadTypeBack:
596                     case FrameLoadTypeForward:
597                     case FrameLoadTypeIndexedBackForward:
598                         if (![[itemURL scheme] isEqual:@"https"])
599                             [request setCachePolicy:NSURLRequestReturnCacheDataElseLoad];
600                         break;
601                     case FrameLoadTypeStandard:
602                     case FrameLoadTypeInternal:
603                         // no-op: leave as protocol default
604                         // FIXME:  I wonder if we ever hit this case
605                         break;
606                     case FrameLoadTypeSame:
607                     case FrameLoadTypeReloadAllowingStaleData:
608                     default:
609                         ASSERT_NOT_REACHED();
610                 }
611
612                 action = [[self _frameLoader] actionInformationForLoadType:loadType isFormSubmission:NO event:nil originalURL:itemOriginalURL];
613             }
614
615             [[self _frameLoader] _loadRequest:request triggeringAction:action loadType:loadType formState:nil];
616             [request release];
617         }
618     }
619 }
620
621 // The general idea here is to traverse the frame tree and the item tree in parallel,
622 // tracking whether each frame already has the content the item requests.  If there is
623 // a match (by URL), we just restore scroll position and recurse.  Otherwise we must
624 // reload that frame, and all its kids.
625 - (void)_recursiveGoToItem:(WebHistoryItem *)item fromItem:(WebHistoryItem *)fromItem withLoadType:(FrameLoadType)type
626 {
627     NSURL *itemURL = [item URL];
628     NSURL *currentURL = [[[self dataSource] request] URL];
629
630     // Always reload the target frame of the item we're going to.  This ensures that we will
631     // do -some- load for the transition, which means a proper notification will be posted
632     // to the app.
633     // The exact URL has to match, including fragment.  We want to go through the _load
634     // method, even if to do a within-page navigation.
635     // The current frame tree and the frame tree snapshot in the item have to match.
636     if (![item isTargetItem] &&
637         [itemURL isEqual:currentURL] &&
638         (([self name] == nil && [item target] == nil) ||[[self name] isEqualToString:[item target]]) &&
639         [self _childFramesMatchItem:item])
640     {
641         // This content is good, so leave it alone and look for children that need reloading
642
643         // Save form state (works from currentItem, since prevItem is nil)
644         ASSERT(!_private->previousItem);
645         [_private->bridge saveDocumentState];
646         [self _saveScrollPositionAndViewStateToItem:_private->currentItem];
647         
648         [_private setCurrentItem:item];
649
650         // Restore form state (works from currentItem)
651         [_private->bridge restoreDocumentState];
652         // Restore the scroll position (taken in favor of going back to the anchor)
653         [self _restoreScrollPositionAndViewState];
654         
655         NSArray *childItems = [item children];
656         int numChildItems = childItems ? [childItems count] : 0;
657         int i;
658         for (i = numChildItems - 1; i >= 0; i--) {
659             WebHistoryItem *childItem = [childItems objectAtIndex:i];
660             NSString *childName = [childItem target];
661             WebHistoryItem *fromChildItem = [fromItem childItemWithName:childName];
662             ASSERT(fromChildItem || [fromItem isTargetItem]);
663             WebFrame *childFrame = [self _immediateChildFrameNamed:childName];
664             ASSERT(childFrame);
665             [childFrame _recursiveGoToItem:childItem fromItem:fromChildItem withLoadType:type];
666         }
667     } else {
668         // We need to reload the content
669         [self _loadItem:item withLoadType:type];
670     }
671 }
672
673 // Main funnel for navigating to a previous location (back/forward, non-search snap-back)
674 // This includes recursion to handle loading into framesets properly
675 - (void)_goToItem:(WebHistoryItem *)item withLoadType:(FrameLoadType)type
676 {
677     ASSERT(![self parentFrame]);
678     // shouldGoToHistoryItem is a private delegate method. This is needed to fix:
679     // <rdar://problem/3951283> can view pages from the back/forward cache that should be disallowed by Parental Controls
680     // Ultimately, history item navigations should go through the policy delegate. That's covered in:
681     // <rdar://problem/3979539> back/forward cache navigations should consult policy delegate
682     if ([[[self webView] _policyDelegateForwarder] webView:[self webView] shouldGoToHistoryItem:item]) {    
683         WebBackForwardList *backForwardList = [[self webView] backForwardList];
684         WebHistoryItem *currItem = [backForwardList currentItem];
685         // Set the BF cursor before commit, which lets the user quickly click back/forward again.
686         // - plus, it only makes sense for the top level of the operation through the frametree,
687         // as opposed to happening for some/one of the page commits that might happen soon
688         [backForwardList goToItem:item];
689         [self _recursiveGoToItem:item fromItem:currItem withLoadType:type];
690     }
691 }
692
693 - (void)_loadURL:(NSURL *)URL referrer:(NSString *)referrer intoChild:(WebFrame *)childFrame
694 {
695     WebHistoryItem *parentItem = _private->currentItem;
696     NSArray *childItems = [parentItem children];
697     FrameLoadType loadType = [[self _frameLoader] loadType];
698     FrameLoadType childLoadType = FrameLoadTypeInternal;
699     WebHistoryItem *childItem = nil;
700
701     // If we're moving in the backforward list, we might want to replace the content
702     // of this child frame with whatever was there at that point.
703     // Reload will maintain the frame contents, LoadSame will not.
704     if (childItems &&
705         (isBackForwardLoadType(loadType)
706          || loadType == FrameLoadTypeReload
707          || loadType == FrameLoadTypeReloadAllowingStaleData))
708     {
709         childItem = [parentItem childItemWithName:[childFrame name]];
710         if (childItem) {
711             // Use the original URL to ensure we get all the side-effects, such as
712             // onLoad handlers, of any redirects that happened. An example of where
713             // this is needed is Radar 3213556.
714             URL = [NSURL _web_URLWithDataAsString:[childItem originalURLString]];
715             // These behaviors implied by these loadTypes should apply to the child frames
716             childLoadType = loadType;
717
718             if (isBackForwardLoadType(loadType))
719                 // For back/forward, remember this item so we can traverse any child items as child frames load
720                 [childFrame->_private setProvisionalItem:childItem];
721             else
722                 // For reload, just reinstall the current item, since a new child frame was created but we won't be creating a new BF item
723                 [childFrame->_private setCurrentItem:childItem];
724         }
725     }
726
727     WebArchive *archive = [[self dataSource] _popSubframeArchiveWithName:[childFrame name]];
728     if (archive)
729         [childFrame loadArchive:archive];
730     else
731         [[childFrame _frameLoader] loadURL:URL referrer:referrer loadType:childLoadType target:nil triggeringEvent:nil form:nil formValues:nil];
732 }
733
734 - (void)_setTitle:(NSString *)title forURL:(NSURL *)URL
735 {
736     [[[WebHistory optionalSharedHistory] itemForURL:URL] setTitle:title];
737     [_private->currentItem setTitle:title];
738 }
739
740 - (void)_saveScrollPositionAndViewStateToItem:(WebHistoryItem *)item
741 {
742     if (item) {
743         NSView <WebDocumentView> *docView = [[self frameView] documentView];
744         NSView *parent = [docView superview];
745         // we might already be detached when this is called from detachFromParent, in which
746         // case we don't want to override real data earlier gathered with (0,0)
747         if (parent) {
748             NSPoint point;
749             if ([docView conformsToProtocol:@protocol(_WebDocumentViewState)]) {
750                 // The view has it's own idea of where it is scrolled to, perhaps because it contains its own
751                 // ScrollView instead of using the one provided by the WebFrame
752                 point = [(id <_WebDocumentViewState>)docView scrollPoint];
753                 [item setViewState:[(id <_WebDocumentViewState>)docView viewState]];
754             } else {
755                 // Parent is the clipview of the DynamicScrollView the WebFrame installs
756                 ASSERT([parent isKindOfClass:[NSClipView class]]);
757                 point = [parent bounds].origin;
758             }
759             [item setScrollPoint:point];
760         }
761     }
762 }
763
764 - (void)_viewWillMoveToHostWindow:(NSWindow *)hostWindow
765 {
766     for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self])
767         [[[frame frameView] documentView] viewWillMoveToHostWindow:hostWindow];
768 }
769
770 - (void)_viewDidMoveToHostWindow
771 {
772     for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self])
773         [[[frame frameView] documentView] viewDidMoveToHostWindow];
774 }
775
776 - (void)_addChild:(WebFrame *)child
777 {
778     [[self _bridge] appendChild:[child _bridge]];
779     [[[child dataSource] _documentLoader] setOverrideEncoding:[[[self dataSource] _documentLoader] overrideEncoding]];  
780 }
781
782 // If we bailed out of a b/f navigation, we might need to set the b/f cursor back to the current
783 // item, because we optimistically move it right away at the start of the operation. But when
784 // alternate content is loaded for an unreachableURL, we don't want to reset the b/f cursor.
785 // Return the item that we would reset to, so we can decide later whether to actually reset.
786 - (WebHistoryItem *)_currentBackForwardListItemToResetTo
787 {
788     if (isBackForwardLoadType([[self _frameLoader] loadType]) && self == [[self webView] mainFrame])
789         return _private->currentItem;
790     return nil;
791 }
792
793 - (WebHistoryItem *)_itemForSavingDocState
794 {
795     // For a standard page load, we will have a previous item set, which will be used to
796     // store the form state.  However, in some cases we will have no previous item, and
797     // the current item is the right place to save the state.  One example is when we
798     // detach a bunch of frames because we are navigating from a site with frames to
799     // another site.  Another is when saving the frame state of a frame that is not the
800     // target of the current navigation (if we even decide to save with that granularity).
801
802     // Because of previousItem's "masking" of currentItem for this purpose, it's important
803     // that previousItem be cleared at the end of a page transition.  We leverage the
804     // checkLoadComplete recursion to achieve this goal.
805
806     return _private->previousItem ? _private->previousItem : _private->currentItem;
807 }
808
809 - (WebHistoryItem *)_itemForRestoringDocState
810 {
811     switch ([[self _frameLoader] loadType]) {
812         case FrameLoadTypeReload:
813         case FrameLoadTypeReloadAllowingStaleData:
814         case FrameLoadTypeSame:
815         case FrameLoadTypeReplace:
816             // Don't restore any form state on reload or loadSame
817             return nil;
818         case FrameLoadTypeBack:
819         case FrameLoadTypeForward:
820         case FrameLoadTypeIndexedBackForward:
821         case FrameLoadTypeInternal:
822         case FrameLoadTypeStandard:
823             return _private->currentItem;
824     }
825     ASSERT_NOT_REACHED();
826     return nil;
827 }
828
829 // Walk the frame tree, telling all frames to save their form state into their current
830 // history item.
831 - (void)_saveDocumentAndScrollState
832 {
833     for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self]) {
834         [[frame _bridge] saveDocumentState];
835         [frame _saveScrollPositionAndViewStateToItem:frame->_private->currentItem];
836     }
837 }
838
839 - (BOOL)_shouldTreatURLAsSameAsCurrent:(NSURL *)URL
840 {
841     WebHistoryItem *item = _private->currentItem;
842     NSString* URLString = [URL _web_originalDataAsString];
843     return [URLString isEqual:[item URLString]] || [URLString isEqual:[item originalURLString]];
844 }    
845
846 // Return next frame to be traversed, visiting children after parent
847 - (WebFrame *)_nextFrameWithWrap:(BOOL)wrapFlag
848 {
849     return Frame([[self _bridge] nextFrameWithWrap:wrapFlag]);
850 }
851
852 // Return previous frame to be traversed, exact reverse order of _nextFrame
853 - (WebFrame *)_previousFrameWithWrap:(BOOL)wrapFlag
854 {
855     return Frame([[self _bridge] previousFrameWithWrap:wrapFlag]);
856 }
857
858 - (BOOL)_shouldCreateRenderers
859 {
860     return [_private->bridge shouldCreateRenderers];
861 }
862
863 - (int)_numPendingOrLoadingRequests:(BOOL)recurse
864 {
865     if (!recurse)
866         return [[self _bridge] numPendingOrLoadingRequests];
867
868     int num = 0;
869     for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self])
870         num += [[frame _bridge] numPendingOrLoadingRequests];
871
872     return num;
873 }
874
875 - (void)_reloadForPluginChanges
876 {
877     for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self]) {
878         NSView <WebDocumentView> *documentView = [[frame frameView] documentView];
879         if (([documentView isKindOfClass:[WebHTMLView class]] && [_private->bridge containsPlugins]))
880             [frame reload];
881     }
882 }
883
884 - (void)_attachScriptDebugger
885 {
886     if (!_private->scriptDebugger)
887         _private->scriptDebugger = [[WebScriptDebugger alloc] initWithWebFrame:self];
888 }
889
890 - (void)_detachScriptDebugger
891 {
892     if (_private->scriptDebugger) {
893         id old = _private->scriptDebugger;
894         _private->scriptDebugger = nil;
895         [old release];
896     }
897 }
898
899 - (void)_recursive_pauseNullEventsForAllNetscapePlugins
900 {
901     for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self]) {
902         NSView <WebDocumentView> *documentView = [[frame frameView] documentView];
903         if ([documentView isKindOfClass:[WebHTMLView class]])
904             [(WebHTMLView *)documentView _pauseNullEventsForAllNetscapePlugins];
905     }
906 }
907
908 - (void)_recursive_resumeNullEventsForAllNetscapePlugins
909 {
910     for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self]) {
911         NSView <WebDocumentView> *documentView = [[frame frameView] documentView];
912         if ([documentView isKindOfClass:[WebHTMLView class]])
913             [(WebHTMLView *)documentView _resumeNullEventsForAllNetscapePlugins];
914     }
915 }
916
917 - (id)_initWithWebFrameView:(WebFrameView *)fv webView:(WebView *)v bridge:(WebFrameBridge *)bridge
918 {
919     self = [super init];
920     if (!self)
921         return nil;
922
923     _private = [[WebFramePrivate alloc] init];
924
925     _private->bridge = bridge;
926
927     if (fv) {
928         [_private setWebFrameView:fv];
929         [fv _setWebFrame:self];
930     }
931     
932     ++WebFrameCount;
933     
934     return self;
935 }
936
937 - (NSArray *)_documentViews
938 {
939     NSMutableArray *result = [NSMutableArray array];
940     for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self]) {
941         id docView = [[frame frameView] documentView];
942         if (docView)
943             [result addObject:docView];
944     }
945         
946     return result;
947 }
948
949 - (void)_updateBackground
950 {
951     BOOL drawsBackground = [[self webView] drawsBackground];
952     NSColor *backgroundColor = [[self webView] backgroundColor];
953
954     for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self]) {
955         // Never call setDrawsBackground:YES here on the scroll view or the background color will
956         // flash between pages loads. setDrawsBackground:YES will be called in _frameLoadCompleted.
957         if (!drawsBackground)
958             [[[frame frameView] _scrollView] setDrawsBackground:NO];
959         [[[frame frameView] _scrollView] setBackgroundColor:backgroundColor];
960         id documentView = [[frame frameView] documentView];
961         if ([documentView respondsToSelector:@selector(setDrawsBackground:)])
962             [documentView setDrawsBackground:drawsBackground];
963         if ([documentView respondsToSelector:@selector(setBackgroundColor:)])
964             [documentView setBackgroundColor:backgroundColor];
965         [[frame _bridge] setDrawsBackground:drawsBackground];
966         [[frame _bridge] setBaseBackgroundColor:backgroundColor];
967     }
968 }
969
970 - (void)_setInternalLoadDelegate:(id)internalLoadDelegate
971 {
972     _private->internalLoadDelegate = internalLoadDelegate;
973 }
974
975 - (id)_internalLoadDelegate
976 {
977     return _private->internalLoadDelegate;
978 }
979
980 - (void)_unmarkAllMisspellings
981 {
982     for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self])
983         [[frame _bridge] unmarkAllMisspellings];
984 }
985
986 - (BOOL)_hasSelection
987 {
988     id documentView = [[self frameView] documentView];    
989     
990     // optimization for common case to avoid creating potentially large selection string
991     if ([documentView isKindOfClass:[WebHTMLView class]]) {
992         DOMRange *selectedDOMRange = [[self _bridge] selectedDOMRange];
993         return selectedDOMRange && ![selectedDOMRange collapsed];
994     }
995     
996     if ([documentView conformsToProtocol:@protocol(WebDocumentText)])
997         return [[documentView selectedString] length] > 0;
998     
999     return NO;
1000 }
1001
1002 - (void)_clearSelection
1003 {
1004     id documentView = [[self frameView] documentView];    
1005     if ([documentView conformsToProtocol:@protocol(WebDocumentText)])
1006         [documentView deselectAll];
1007 }
1008
1009 #ifndef NDEBUG
1010
1011 - (BOOL)_atMostOneFrameHasSelection;
1012 {
1013     // FIXME: 4186050 is one known case that makes this debug check fail
1014     BOOL found = NO;
1015     for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self]) {
1016         if ([frame _hasSelection]) {
1017             if (found)
1018                 return NO;
1019             found = YES;
1020         }
1021     }
1022
1023     return YES;
1024 }
1025 #endif
1026
1027 - (WebFrame *)_findFrameWithSelection
1028 {
1029     for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self])
1030         if ([frame _hasSelection])
1031             return frame;
1032
1033     return nil;
1034 }
1035
1036 - (void)_clearSelectionInOtherFrames
1037 {
1038     // We rely on WebDocumentSelection protocol implementors to call this method when they become first 
1039     // responder. It would be nicer to just notice first responder changes here instead, but there's no 
1040     // notification sent when the first responder changes in general (Radar 2573089).
1041     WebFrame *frameWithSelection = [[[self webView] mainFrame] _findFrameWithSelection];
1042     if (frameWithSelection != self)
1043         [frameWithSelection _clearSelection];
1044
1045     // While we're in the general area of selection and frames, check that there is only one now.
1046     ASSERT([[[self webView] mainFrame] _atMostOneFrameHasSelection]);
1047 }
1048
1049 - (void)_addPlugInView:(NSView *)plugInView
1050 {
1051     ASSERT([plugInView respondsToSelector:@selector(setWebFrame:)]);
1052     ASSERT(![_private->plugInViews containsObject:plugInView]);
1053     
1054     if (!_private->plugInViews)
1055         _private->plugInViews = [[NSMutableSet alloc] init];
1056         
1057     [plugInView setWebFrame:self];
1058     [_private->plugInViews addObject:plugInView];
1059 }
1060
1061 - (void)_removeAllPlugInViews
1062 {
1063     if (!_private->plugInViews)
1064         return;
1065     
1066     [_private->plugInViews makeObjectsPerformSelector:@selector(setWebFrame:) withObject:nil];
1067     [_private->plugInViews release];
1068     _private->plugInViews = nil;
1069 }
1070
1071 // This is called when leaving a page or closing the WebView
1072 - (void)_willCloseURL
1073 {
1074     [self _removeAllPlugInViews];
1075 }
1076
1077 - (BOOL)_isMainFrame
1078 {
1079     return self == [[self webView] mainFrame];
1080 }
1081
1082 - (void)_addInspector:(WebInspector *)inspector
1083 {
1084     if (!_private->inspectors)
1085         _private->inspectors = [[NSMutableSet alloc] init];
1086     ASSERT(![_private->inspectors containsObject:inspector]);
1087     [_private->inspectors addObject:inspector];
1088 }
1089
1090 - (void)_removeInspector:(WebInspector *)inspector
1091 {
1092     ASSERT([_private->inspectors containsObject:inspector]);
1093     [_private->inspectors removeObject:inspector];
1094 }
1095
1096 - (WebFrameLoader *)_frameLoader
1097 {
1098     return [_private->bridge frameLoader];
1099 }
1100
1101 - (void)_prepareForDataSourceReplacement
1102 {
1103     if (![[self _frameLoader] dataSource]) {
1104         ASSERT(![self _childFrameCount]);
1105         return;
1106     }
1107     
1108     // Make sure that any work that is triggered by resigning first reponder can get done.
1109     // The main example where this came up is the textDidEndEditing that is sent to the
1110     // FormsDelegate (3223413).  We need to do this before _detachChildren, since that will
1111     // remove the views as a side-effect of freeing the bridge, at which point we can't
1112     // post the FormDelegate messages.
1113     //
1114     // Note that this can also take FirstResponder away from a child of our frameView that
1115     // is not in a child frame's view.  This is OK because we are in the process
1116     // of loading new content, which will blow away all editors in this top frame, and if
1117     // a non-editor is firstReponder it will not be affected by endEditingFor:.
1118     // Potentially one day someone could write a DocView whose editors were not all
1119     // replaced by loading new content, but that does not apply currently.
1120     NSView *frameView = [self frameView];
1121     NSWindow *window = [frameView window];
1122     NSResponder *firstResp = [window firstResponder];
1123     if ([firstResp isKindOfClass:[NSView class]]
1124         && [(NSView *)firstResp isDescendantOf:frameView])
1125     {
1126         [window endEditingFor:firstResp];
1127     }
1128     
1129     [[self _frameLoader] detachChildren];
1130 }
1131
1132 - (void)_frameLoadCompleted
1133 {
1134     // Note: Can be called multiple times.
1135     // Even if already complete, we might have set a previous item on a frame that
1136     // didn't do any data loading on the past transaction. Make sure to clear these out.
1137     NSScrollView *sv = [[self frameView] _scrollView];
1138     if ([[self webView] drawsBackground])
1139         [sv setDrawsBackground:YES];
1140     [_private setPreviousItem:nil];
1141 }
1142
1143 static inline WebDataSource *dataSource(WebDocumentLoader *loader)
1144 {
1145     return [(WebDocumentLoaderMac *)loader dataSource];
1146 }
1147
1148 - (WebDataSource *)_dataSourceForDocumentLoader:(WebDocumentLoader *)loader
1149 {
1150     return dataSource(loader);
1151 }
1152
1153 - (WebDocumentLoader *)_createDocumentLoaderWithRequest:(NSURLRequest *)request
1154 {
1155     WebDocumentLoaderMac *loader = [[WebDocumentLoaderMac alloc] initWithRequest:request];
1156     
1157     WebDataSource *dataSource = [[WebDataSource alloc] _initWithDocumentLoader:loader];
1158     [loader setDataSource:dataSource];
1159     [dataSource release];
1160
1161     return loader;
1162 }
1163
1164 /*
1165     There is a race condition between the layout and load completion that affects restoring the scroll position.
1166     We try to restore the scroll position at both the first layout and upon load completion.
1167
1168     1) If first layout happens before the load completes, we want to restore the scroll position then so that the
1169        first time we draw the page is already scrolled to the right place, instead of starting at the top and later
1170        jumping down.  It is possible that the old scroll position is past the part of the doc laid out so far, in
1171        which case the restore silent fails and we will fix it in when we try to restore on doc completion.
1172     2) If the layout happens after the load completes, the attempt to restore at load completion time silently
1173        fails.  We then successfully restore it when the layout happens.
1174  */
1175
1176 - (void)_restoreScrollPositionAndViewState
1177 {
1178     ASSERT(_private->currentItem);
1179     NSView <WebDocumentView> *docView = [[self frameView] documentView];
1180     NSPoint point = [_private->currentItem scrollPoint];
1181     if ([docView conformsToProtocol:@protocol(_WebDocumentViewState)]) {        
1182         id state = [_private->currentItem viewState];
1183         if (state) {
1184             [(id <_WebDocumentViewState>)docView setViewState:state];
1185         }
1186         
1187         [(id <_WebDocumentViewState>)docView setScrollPoint:point];
1188     } else {
1189         [docView scrollPoint:point];
1190     }
1191 }
1192
1193 @end
1194
1195 @implementation WebFrame (WebPrivate)
1196
1197 // FIXME: this exists only as a convenience for Safari, consider moving there
1198 - (BOOL)_isDescendantOfFrame:(WebFrame *)ancestor
1199 {
1200     return [[self _bridge] isDescendantOfFrame:[ancestor _bridge]];
1201 }
1202
1203 - (void)_setShouldCreateRenderers:(BOOL)f
1204 {
1205     [_private->bridge setShouldCreateRenderers:f];
1206 }
1207
1208 - (NSColor *)_bodyBackgroundColor
1209 {
1210     return [_private->bridge bodyBackgroundColor];
1211 }
1212
1213 - (BOOL)_isFrameSet
1214 {
1215     return [_private->bridge isFrameSet];
1216 }
1217
1218 - (BOOL)_firstLayoutDone
1219 {
1220     return [[self _frameLoader] firstLayoutDone];
1221 }
1222
1223 - (WebFrameLoadType)_loadType
1224 {
1225     return (WebFrameLoadType)[[self _frameLoader] loadType];
1226 }
1227
1228 @end
1229
1230 @implementation WebFormState : NSObject
1231
1232 - (id)initWithForm:(DOMElement *)form values:(NSDictionary *)values sourceFrame:(WebFrame *)sourceFrame
1233 {
1234     self = [super init];
1235     if (!self)
1236         return nil;
1237     
1238     _form = [form retain];
1239     _values = [values copy];
1240     _sourceFrame = [sourceFrame retain];
1241     return self;
1242 }
1243
1244 - (void)dealloc
1245 {
1246     [_form release];
1247     [_values release];
1248     [_sourceFrame release];
1249     [super dealloc];
1250 }
1251
1252 - (DOMElement *)form
1253 {
1254     return _form;
1255 }
1256
1257 - (NSDictionary *)values
1258 {
1259     return _values;
1260 }
1261
1262 - (WebFrame *)sourceFrame
1263 {
1264     return _sourceFrame;
1265 }
1266
1267 @end
1268
1269 @implementation WebFrame
1270
1271 - (id)init
1272 {
1273     return [self initWithName:nil webFrameView:nil webView:nil];
1274 }
1275
1276 // FIXME: this method can't work any more and should be marked deprecated
1277 - (id)initWithName:(NSString *)n webFrameView:(WebFrameView *)fv webView:(WebView *)v
1278 {
1279     return [self _initWithWebFrameView:fv webView:v bridge:nil];
1280 }
1281
1282 - (void)dealloc
1283 {
1284     ASSERT(_private->bridge == nil);
1285     [_private release];
1286
1287     --WebFrameCount;
1288
1289     [super dealloc];
1290 }
1291
1292 - (void)finalize
1293 {
1294     ASSERT(_private->bridge == nil);
1295
1296     --WebFrameCount;
1297
1298     [super finalize];
1299 }
1300
1301 - (NSString *)name
1302 {
1303     return [[self _bridge] name];
1304 }
1305
1306 - (WebFrameView *)frameView
1307 {
1308     return _private->webFrameView;
1309 }
1310
1311 - (WebView *)webView
1312 {
1313     return [[[self _bridge] page] webView];
1314 }
1315
1316 - (DOMDocument *)DOMDocument
1317 {
1318     return [[self dataSource] _isDocumentHTML] ? [_private->bridge DOMDocument] : nil;
1319 }
1320
1321 - (DOMHTMLElement *)frameElement
1322 {
1323     return [[self webView] mainFrame] != self ? [_private->bridge frameElement] : nil;
1324 }
1325
1326 - (WebDataSource *)provisionalDataSource
1327 {
1328     return [[self _frameLoader] provisionalDataSource];
1329 }
1330
1331 - (WebDataSource *)dataSource
1332 {
1333     return [[self _frameLoader] dataSource];
1334 }
1335
1336 - (void)loadRequest:(NSURLRequest *)request
1337 {
1338     // FIXME: is this the right place to reset loadType? Perhaps this should be done
1339     // after loading is finished or aborted.
1340     [[self _frameLoader] setLoadType:FrameLoadTypeStandard];
1341     [[self _frameLoader] _loadRequest:request archive:nil];
1342 }
1343
1344 - (void)_loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)URL unreachableURL:(NSURL *)unreachableURL
1345 {
1346     NSURLRequest *request = [self _webDataRequestForData:data 
1347                                                 MIMEType:MIMEType 
1348                                         textEncodingName:encodingName 
1349                                                  baseURL:URL
1350                                           unreachableURL:unreachableURL];
1351     [self loadRequest:request];
1352 }
1353
1354
1355 - (void)loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)URL
1356 {
1357     [self _loadData:data MIMEType:MIMEType textEncodingName:encodingName baseURL:URL unreachableURL:nil];
1358 }
1359
1360 - (void)_loadHTMLString:(NSString *)string baseURL:(NSURL *)URL unreachableURL:(NSURL *)unreachableURL
1361 {
1362     NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
1363     [self _loadData:data MIMEType:nil textEncodingName:@"UTF-8" baseURL:URL unreachableURL:unreachableURL];
1364 }
1365
1366 - (void)loadHTMLString:(NSString *)string baseURL:(NSURL *)URL
1367 {
1368     [self _loadHTMLString:string baseURL:URL unreachableURL:nil];
1369 }
1370
1371 - (void)loadAlternateHTMLString:(NSString *)string baseURL:(NSURL *)URL forUnreachableURL:(NSURL *)unreachableURL
1372 {
1373     [self _loadHTMLString:string baseURL:URL unreachableURL:unreachableURL];
1374 }
1375
1376 - (void)loadArchive:(WebArchive *)archive
1377 {
1378     WebResource *mainResource = [archive mainResource];
1379     if (mainResource) {
1380         NSURLRequest *request = [self _webDataRequestForData:[mainResource data] 
1381                                                     MIMEType:[mainResource MIMEType]
1382                                             textEncodingName:[mainResource textEncodingName]
1383                                                      baseURL:[mainResource URL]
1384                                               unreachableURL:nil];
1385         [[self _frameLoader] _loadRequest:request archive:archive];
1386     }
1387 }
1388
1389 - (void)stopLoading
1390 {
1391     [[self _frameLoader] stopLoading];
1392 }
1393
1394 - (void)reload
1395 {
1396     [[self _frameLoader] reload];
1397 }
1398
1399 - (WebFrame *)findFrameNamed:(NSString *)name
1400 {
1401     return Frame([[self _bridge] findFrameNamed:name]);
1402 }
1403
1404 - (WebFrame *)parentFrame
1405 {
1406     return [[Frame([[self _bridge] parent]) retain] autorelease];
1407 }
1408
1409 - (NSArray *)childFrames
1410 {
1411     NSMutableArray *children = [NSMutableArray arrayWithCapacity:[self _childFrameCount]];
1412     for (WebFrame *child = [self _firstChildFrame]; child; child = [child _nextSiblingFrame])
1413         [children addObject:child];
1414
1415     return children;
1416 }
1417
1418 @end
1419
1420 @implementation WebFrame (WebFrameLoaderClient)
1421
1422 - (void)_resetBackForwardList
1423 {
1424     // Note this doesn't verify the current load type as a b/f operation because it is called from
1425     // a subframe in the case of a delegate bailing out of the nav before it even gets to provisional state.
1426     ASSERT(self == [[self webView] mainFrame]);
1427     WebHistoryItem *resetItem = _private->currentItem;
1428     if (resetItem)
1429         [[[self webView] backForwardList] goToItem:resetItem];
1430 }
1431
1432 - (void)_invalidateCurrentItemPageCache
1433 {
1434     // When we are pre-commit, the currentItem is where the pageCache data resides
1435     NSDictionary *pageCache = [_private->currentItem pageCache];
1436
1437     [[self _bridge] invalidatePageCache:pageCache];
1438     
1439     // We're assuming that WebCore invalidates its pageCache state in didNotOpen:pageCache:
1440     [_private->currentItem setHasPageCache:NO];
1441 }
1442
1443 - (BOOL)_provisionalItemIsTarget
1444 {
1445     return [_private->provisionalItem isTargetItem];
1446 }
1447
1448 - (BOOL)_loadProvisionalItemFromPageCache
1449 {
1450     WebHistoryItem *item = _private->provisionalItem;
1451     if (![item hasPageCache])
1452         return NO;
1453     NSDictionary *pageCache = [item pageCache];
1454     if (![pageCache objectForKey:WebCorePageCacheStateKey])
1455         return NO;
1456     LOG(PageCache, "Restoring page from back/forward cache, %@", [item URL]);
1457     [[self provisionalDataSource] _loadFromPageCache:pageCache];
1458     return YES;
1459 }
1460
1461 - (BOOL)_privateBrowsingEnabled
1462 {
1463     return [[[self webView] preferences] privateBrowsingEnabled];
1464 }
1465
1466 - (void)_makeDocumentView
1467 {
1468     NSView <WebDocumentView> *documentView = [_private->webFrameView _makeDocumentViewForDataSource:[[self _frameLoader] dataSource]];
1469     if (!documentView)
1470         return;
1471
1472     // FIXME: We could save work and not do this for a top-level view that is not a WebHTMLView.
1473     WebFrameView *v = _private->webFrameView;
1474     [_private->bridge createFrameViewWithNSView:documentView marginWidth:[v _marginWidth] marginHeight:[v _marginHeight]];
1475     [self _updateBackground];
1476     [_private->bridge installInFrame:[v _scrollView]];
1477
1478     // Call setDataSource on the document view after it has been placed in the view hierarchy.
1479     // This what we for the top-level view, so should do this for views in subframes as well.
1480     [documentView setDataSource:[[self _frameLoader] dataSource]];
1481 }
1482
1483 - (void)_forceLayout
1484 {
1485     NSView <WebDocumentView> *view = [[self frameView] documentView];
1486     if ([view isKindOfClass:[WebHTMLView class]])
1487         [(WebHTMLView *)view setNeedsToApplyStyles:YES];
1488     [view setNeedsLayout:YES];
1489     [view layout];
1490 }
1491
1492 - (void)_updateHistoryForCommit
1493 {
1494     WebFrameLoadType type = [[self _frameLoader] loadType];
1495     if (isBackForwardLoadType(type) ||
1496         (type == WebFrameLoadTypeReload && [[self provisionalDataSource] unreachableURL] != nil)) {
1497         // Once committed, we want to use current item for saving DocState, and
1498         // the provisional item for restoring state.
1499         // Note previousItem must be set before we close the URL, which will
1500         // happen when the data source is made non-provisional below
1501         [_private setPreviousItem:_private->currentItem];
1502         ASSERT(_private->provisionalItem);
1503         [_private setCurrentItem:_private->provisionalItem];
1504         [_private setProvisionalItem:nil];
1505     }
1506 }
1507
1508 - (void)_updateHistoryForReload
1509 {
1510     WebHistoryItem *currItem = _private->currentItem;
1511     LOG(PageCache, "Clearing back/forward cache, %@\n", [currItem URL]);
1512     [currItem setHasPageCache:NO];
1513     if ([[self _frameLoader] loadType] == WebFrameLoadTypeReload)
1514         [self _saveScrollPositionAndViewStateToItem:currItem];
1515     WebDataSource *dataSource = [[self _frameLoader] dataSource];
1516     NSURLRequest *request = [dataSource request];
1517     // Sometimes loading a page again leads to a different result because of cookies. Bugzilla 4072
1518     if ([request _webDataRequestUnreachableURL] == nil)
1519         [currItem setURL:[request URL]];
1520     // Update the last visited time. Mostly interesting for URL autocompletion statistics.
1521     NSURL *URL = [[[[dataSource _documentLoader] originalRequestCopy] URL] _webkit_canonicalize];
1522     WebHistory *sharedHistory = [WebHistory optionalSharedHistory];
1523     WebHistoryItem *oldItem = [sharedHistory itemForURL:URL];
1524     if (oldItem)
1525         [sharedHistory setLastVisitedTimeInterval:[NSDate timeIntervalSinceReferenceDate] forItem:oldItem];
1526 }
1527
1528 - (void)_updateHistoryForStandardLoad
1529 {
1530     WebDataSource *dataSource = [[self _frameLoader] dataSource];
1531     if (![[dataSource _documentLoader] isClientRedirect]) {
1532         NSURL *URL = [dataSource _URLForHistory];
1533         if (URL && ![URL _web_isEmpty]) {
1534             ASSERT([self webView]);
1535             if (![[[self webView] preferences] privateBrowsingEnabled]) {
1536                 WebHistoryItem *entry = [[WebHistory optionalSharedHistory] addItemForURL:URL];
1537                 if ([dataSource pageTitle])
1538                     [entry setTitle:[dataSource pageTitle]];                            
1539             }
1540             [self _addBackForwardItemClippedAtTarget:YES];
1541         }
1542     } else {
1543         NSURLRequest *request = [dataSource request];
1544         
1545         // Update the URL in the BF list that we made before the redirect, unless
1546         // this is alternate content for an unreachable URL (we want the BF list
1547         // item to remember the unreachable URL in case it becomes reachable later).
1548         if ([request _webDataRequestUnreachableURL] == nil) {
1549             [_private->currentItem setURL:[request URL]];
1550
1551             // clear out the form data so we don't repost it to the wrong place if we
1552             // ever go back/forward to this item
1553             [_private->currentItem _setFormInfoFromRequest:request];
1554
1555             // We must also clear out form data so we don't try to restore it into the incoming page,
1556             // see -_opened
1557         }
1558     }
1559 }
1560
1561 - (void)_updateHistoryForBackForwardNavigation
1562 {
1563     // Must grab the current scroll position before disturbing it
1564     [self _saveScrollPositionAndViewStateToItem:_private->previousItem];
1565 }
1566
1567 - (void)_updateHistoryForInternalLoad
1568 {
1569     // Add an item to the item tree for this frame
1570     ASSERT(![[[[self _frameLoader] dataSource] _documentLoader] isClientRedirect]);
1571     WebFrame *parentFrame = [self parentFrame];
1572     if (parentFrame) {
1573         WebHistoryItem *parentItem = parentFrame->_private->currentItem;
1574         // The only case where parentItem==nil should be when a parent frame loaded an
1575         // empty URL, which doesn't set up a current item in that parent.
1576         if (parentItem)
1577             [parentItem addChildItem:[self _createItem:YES]];
1578     } else {
1579         // See 3556159. It's not clear if it's valid to be in WebFrameLoadTypeOnLoadEvent
1580         // for a top-level frame, but that was a likely explanation for those crashes,
1581         // so let's guard against it.
1582         // ...and all WebFrameLoadTypeOnLoadEvent uses were folded to WebFrameLoadTypeInternal
1583         LOG_ERROR("no parent frame in transitionToCommitted:, WebFrameLoadTypeInternal");
1584     }
1585 }
1586
1587 - (LoadErrorResetToken *)_tokenForLoadErrorReset
1588 {
1589     return (LoadErrorResetToken*)[[self _currentBackForwardListItemToResetTo] retain];
1590 }
1591
1592 - (void)_resetAfterLoadError:(LoadErrorResetToken *)token
1593 {
1594     WebHistoryItem *item = (WebHistoryItem *)token;
1595     if (item)
1596         [[[self webView] backForwardList] goToItem:item];
1597     [item release];
1598 }
1599
1600 - (void)_doNotResetAfterLoadError:(LoadErrorResetToken *)token
1601 {
1602     WebHistoryItem *item = (WebHistoryItem *)token;
1603     [item release];
1604 }
1605
1606 - (void)_dispatchDidHandleOnloadEventsForFrame
1607 {
1608     WebView *webView = [self webView];
1609     [[webView _frameLoadDelegateForwarder] webView:webView didHandleOnloadEventsForFrame:self];
1610 }
1611
1612 - (void)_dispatchDidReceiveServerRedirectForProvisionalLoadForFrame
1613 {
1614     WebView *webView = [self webView];
1615     [[webView _frameLoadDelegateForwarder] webView:webView
1616        didReceiveServerRedirectForProvisionalLoadForFrame:self];
1617 }
1618
1619 - (id)_dispatchIdentifierForInitialRequest:(NSURLRequest *)clientRequest fromDocumentLoader:(WebDocumentLoader *)loader
1620 {
1621     WebView *webView = [self webView];
1622     id resourceLoadDelegate = [webView resourceLoadDelegate];
1623     
1624     if ([webView _resourceLoadDelegateImplementations].delegateImplementsIdentifierForRequest)
1625         return [resourceLoadDelegate webView:webView identifierForInitialRequest:clientRequest fromDataSource:dataSource(loader)];
1626
1627     return [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView identifierForInitialRequest:clientRequest fromDataSource:dataSource(loader)];
1628 }
1629
1630 - (NSURLRequest *)_dispatchResource:(id)identifier willSendRequest:(NSURLRequest *)clientRequest redirectResponse:(NSURLResponse *)redirectResponse fromDocumentLoader:(WebDocumentLoader *)loader
1631 {
1632     WebView *webView = [self webView];
1633     id resourceLoadDelegate = [webView resourceLoadDelegate];
1634
1635     if ([webView _resourceLoadDelegateImplementations].delegateImplementsWillSendRequest)
1636         return [resourceLoadDelegate webView:webView resource:identifier willSendRequest:clientRequest redirectResponse:redirectResponse fromDataSource:dataSource(loader)];
1637     else
1638         return [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier willSendRequest:clientRequest redirectResponse:redirectResponse fromDataSource:dataSource(loader)];
1639 }
1640
1641 - (void)_dispatchDidReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)currentWebChallenge forResource:(id)identifier fromDocumentLoader:(WebDocumentLoader *)loader
1642 {
1643     WebView *webView = [self webView];
1644     id resourceLoadDelegate = [webView resourceLoadDelegate];
1645
1646     if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidReceiveAuthenticationChallenge)
1647         [resourceLoadDelegate webView:webView resource:identifier didReceiveAuthenticationChallenge:currentWebChallenge fromDataSource:dataSource(loader)];
1648     else
1649         [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didReceiveAuthenticationChallenge:currentWebChallenge fromDataSource:dataSource(loader)];
1650 }
1651
1652 - (void)_dispatchDidCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)currentWebChallenge forResource:(id)identifier fromDocumentLoader:(WebDocumentLoader *)loader
1653 {
1654     WebView *webView = [self webView];
1655     id resourceLoadDelegate = [webView resourceLoadDelegate];
1656
1657     if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidCancelAuthenticationChallenge)
1658         [resourceLoadDelegate webView:webView resource:identifier didCancelAuthenticationChallenge:currentWebChallenge fromDataSource:dataSource(loader)];
1659     else
1660         [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didCancelAuthenticationChallenge:currentWebChallenge fromDataSource:dataSource(loader)];
1661 }
1662
1663 - (void)_dispatchResource:(id)identifier didReceiveResponse:(NSURLResponse *)r fromDocumentLoader:(WebDocumentLoader *)loader
1664 {
1665     WebView *webView = [self webView];
1666
1667     if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidReceiveResponse)
1668         [[webView resourceLoadDelegate] webView:webView resource:identifier didReceiveResponse:r fromDataSource:dataSource(loader)];
1669     else
1670         [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didReceiveResponse:r fromDataSource:dataSource(loader)];
1671 }
1672
1673 - (void)_dispatchResource:(id)identifier didReceiveContentLength:(int)lengthReceived fromDocumentLoader:(WebDocumentLoader *)loader
1674 {
1675     WebView *webView = [self webView];
1676
1677     if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidReceiveContentLength)
1678         [[webView resourceLoadDelegate] webView:webView resource:identifier didReceiveContentLength:(WebNSUInteger)lengthReceived fromDataSource:dataSource(loader)];
1679     else
1680         [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didReceiveContentLength:(WebNSUInteger)lengthReceived fromDataSource:dataSource(loader)];
1681 }
1682
1683 - (void)_dispatchResource:(id)identifier didFinishLoadingFromDocumentLoader:(WebDocumentLoader *)loader
1684 {
1685     WebView *webView = [self webView];
1686     
1687     if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidFinishLoadingFromDataSource)
1688         [[webView resourceLoadDelegate] webView:webView resource:identifier didFinishLoadingFromDataSource:dataSource(loader)];
1689     else
1690         [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didFinishLoadingFromDataSource:dataSource(loader)];
1691 }
1692
1693
1694 - (void)_dispatchResource:(id)identifier didFailLoadingWithError:error fromDocumentLoader:(WebDocumentLoader *)loader
1695 {
1696     WebView *webView = [self webView];
1697     [[webView _resourceLoadDelegateForwarder] webView:webView resource:identifier didFailLoadingWithError:error fromDataSource:dataSource(loader)];
1698 }
1699
1700 - (void)_dispatchDidCancelClientRedirectForFrame
1701 {
1702     WebView *webView = [self webView];
1703     [[webView _frameLoadDelegateForwarder] webView:webView didCancelClientRedirectForFrame:self];
1704 }
1705
1706 - (void)_dispatchWillPerformClientRedirectToURL:(NSURL *)URL delay:(NSTimeInterval)seconds fireDate:(NSDate *)date
1707 {
1708     WebView *webView = [self webView];   
1709     [[webView _frameLoadDelegateForwarder] webView:webView
1710                          willPerformClientRedirectToURL:URL
1711                                                   delay:seconds
1712                                                fireDate:date
1713                                                forFrame:self];
1714 }
1715
1716 - (void)_dispatchDidChangeLocationWithinPageForFrame
1717 {
1718     WebView *webView = [self webView];   
1719     [[webView _frameLoadDelegateForwarder] webView:webView didChangeLocationWithinPageForFrame:self];
1720 }
1721
1722 - (void)_dispatchWillCloseFrame
1723 {
1724     WebView *webView = [self webView];   
1725     [[webView _frameLoadDelegateForwarder] webView:webView willCloseFrame:self];
1726 }
1727
1728 - (void)_dispatchDidReceiveIcon:(NSImage *)icon
1729 {
1730     WebView *webView = [self webView];   
1731     [[webView _frameLoadDelegateForwarder] webView:webView didReceiveIcon:icon forFrame:self];
1732 }
1733
1734 - (void)_dispatchDidStartProvisionalLoadForFrame
1735 {
1736     WebView *webView = [self webView];   
1737     [[webView _frameLoadDelegateForwarder] webView:webView didStartProvisionalLoadForFrame:self];    
1738 }
1739
1740 - (void)_dispatchDidReceiveTitle:(NSString *)title
1741 {
1742     WebView *webView = [self webView];   
1743     [[webView _frameLoadDelegateForwarder] webView:webView didReceiveTitle:title forFrame:self];
1744 }
1745
1746 - (void)_dispatchDidCommitLoadForFrame
1747 {
1748     WebView *webView = [self webView];   
1749     [[webView _frameLoadDelegateForwarder] webView:webView didCommitLoadForFrame:self];
1750 }
1751
1752 - (void)_dispatchDidFailProvisionalLoadWithError:(NSError *)error
1753 {
1754     WebView *webView = [self webView];   
1755     [[webView _frameLoadDelegateForwarder] webView:webView didFailProvisionalLoadWithError:error forFrame:self];
1756 }
1757
1758 - (void)_dispatchDidFailLoadWithError:(NSError *)error
1759 {
1760     WebView *webView = [self webView];   
1761     [[webView _frameLoadDelegateForwarder] webView:webView didFailLoadWithError:error forFrame:self];
1762 }
1763
1764 - (void)_dispatchDidFinishLoadForFrame
1765 {
1766     WebView *webView = [self webView];   
1767     [[webView _frameLoadDelegateForwarder] webView:webView didFinishLoadForFrame:self];
1768 }
1769
1770 - (void)_dispatchDidFirstLayoutInFrame
1771 {
1772     WebView *webView = [self webView];
1773     [[webView _frameLoadDelegateForwarder] webView:webView didFirstLayoutInFrame:self];
1774 }
1775
1776 - (WebFrame *)_dispatchCreateWebViewWithRequest:(NSURLRequest *)request
1777 {
1778     WebView *currentWebView = [self webView];
1779     id wd = [currentWebView UIDelegate];
1780     if ([wd respondsToSelector:@selector(webView:createWebViewWithRequest:)])
1781         return [[wd webView:currentWebView createWebViewWithRequest:request] mainFrame];
1782
1783     return [[[WebDefaultUIDelegate sharedUIDelegate] webView:currentWebView createWebViewWithRequest:request] mainFrame];
1784 }
1785
1786 - (void)_dispatchShow
1787 {
1788     WebView *webView = [self webView];
1789     [[webView _UIDelegateForwarder] webViewShow:webView];
1790 }
1791
1792 - (void)_dispatchDecidePolicyForMIMEType:(NSString *)MIMEType request:(NSURLRequest *)request decisionListener:(WebPolicyDecisionListener *)decisionListener
1793 {
1794     WebView *webView = [self webView];
1795
1796     [[webView _policyDelegateForwarder] webView:webView decidePolicyForMIMEType:MIMEType request:request frame:self decisionListener:decisionListener];
1797 }
1798
1799 - (void)_dispatchDecidePolicyForNewWindowAction:(NSDictionary *)action request:(NSURLRequest *)request newFrameName:(NSString *)frameName decisionListener:(WebPolicyDecisionListener *)decisionListener
1800 {
1801     WebView *webView = [self webView];
1802     [[webView _policyDelegateForwarder] webView:webView
1803             decidePolicyForNewWindowAction:action
1804                                    request:request
1805                               newFrameName:frameName
1806                           decisionListener:decisionListener];
1807 }
1808
1809 - (void)_dispatchDecidePolicyForNavigationAction:(NSDictionary *)action request:(NSURLRequest *)request decisionListener:(WebPolicyDecisionListener *)decisionListener
1810 {
1811     WebView *webView = [self webView];
1812     [[webView _policyDelegateForwarder] webView:webView
1813                 decidePolicyForNavigationAction:action
1814                                         request:request
1815                                           frame:self
1816                                decisionListener:decisionListener];
1817 }
1818
1819 - (void)_dispatchUnableToImplementPolicyWithError:(NSError *)error
1820 {
1821     WebView *webView = [self webView];
1822     [[webView _policyDelegateForwarder] webView:webView unableToImplementPolicyWithError:error frame:self];    
1823 }
1824
1825 - (void)_detachedFromParent1
1826 {
1827     [self _saveScrollPositionAndViewStateToItem:_private->currentItem];
1828 }
1829
1830 - (void)_detachedFromParent2
1831 {
1832     [_private->inspectors makeObjectsPerformSelector:@selector(_webFrameDetached:) withObject:self];
1833     [_private->webFrameView _setWebFrame:nil]; // needed for now to be compatible w/ old behavior
1834 }
1835
1836 - (void)_detachedFromParent3
1837 {
1838     [_private setWebFrameView:nil];
1839 }
1840
1841 - (void)_detachedFromParent4
1842 {
1843     _private->bridge = nil;
1844 }
1845
1846 - (void)_updateHistoryAfterClientRedirect
1847 {
1848     // Clear out form data so we don't try to restore it into the incoming page.  Must happen after
1849     // khtml has closed the URL and saved away the form state.
1850     WebHistoryItem *item = _private->currentItem;
1851     [item setDocumentState:nil];
1852     [item setScrollPoint:NSZeroPoint];
1853 }
1854
1855 - (void)_loadedFromPageCache
1856 {
1857     // Release the resources kept in the page cache.
1858     // They will be reset when we leave this page.
1859     // The WebCore side of the page cache will have already been invalidated by
1860     // the bridge to prevent premature release.
1861     [_private->currentItem setHasPageCache:NO];
1862 }
1863
1864 - (void)_downloadWithLoadingConnection:(NSURLConnection *)connection request:(NSURLRequest *)request response:(NSURLResponse *)response proxy:(id)proxy
1865 {
1866     [WebDownload _downloadWithLoadingConnection:connection
1867                                         request:request
1868                                        response:response
1869                                        delegate:[[self webView] downloadDelegate]
1870                                           proxy:proxy];
1871 }
1872
1873 - (void)_setDocumentViewFromPageCache:(NSDictionary *)pageCache
1874 {
1875     NSView <WebDocumentView> *cachedView = [pageCache objectForKey:WebPageCacheDocumentViewKey];
1876     ASSERT(cachedView != nil);
1877     [[self frameView] _setDocumentView:cachedView];
1878 }
1879
1880 - (void)_setCopiesOnScroll
1881 {
1882     [[[[self frameView] _scrollView] contentView] setCopiesOnScroll:YES];
1883 }
1884
1885 @end