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