2 * Copyright (C) 2005, 2006 Apple Computer, Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
29 #import "WebFrameInternal.h"
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 "WebFormDataStream.h"
40 #import "WebFrameBridge.h"
41 #import "WebFrameLoadDelegate.h"
42 #import "WebFrameLoader.h"
43 #import "WebFrameViewInternal.h"
44 #import "WebHTMLRepresentationPrivate.h"
45 #import "WebHTMLViewInternal.h"
46 #import "WebHTMLViewPrivate.h"
47 #import "WebHistoryItemPrivate.h"
48 #import "WebHistoryPrivate.h"
49 #import "WebKitErrorsPrivate.h"
50 #import "WebKitLogging.h"
51 #import "WebKitNSStringExtras.h"
52 #import "WebKitStatisticsPrivate.h"
53 #import "WebNSObjectExtras.h"
54 #import "WebNSURLExtras.h"
55 #import "WebNSURLRequestExtras.h"
56 #import "WebNetscapePluginEmbeddedView.h"
57 #import "WebNullPluginView.h"
59 #import "WebPluginController.h"
60 #import "WebPreferencesPrivate.h"
61 #import "WebResourceLoadDelegate.h"
62 #import "WebResourcePrivate.h"
63 #import "WebScriptDebugDelegatePrivate.h"
64 #import "WebUIDelegate.h"
65 #import "WebViewInternal.h"
66 #import <WebKit/DOM.h>
67 #import <WebKitSystemInterface.h>
68 #import <objc/objc-runtime.h>
71 Here is the current behavior matrix for four types of navigations:
75 Restore form state: YES
76 Restore scroll and focus state: YES
77 WF Cache policy: NSURLRequestUseProtocolCachePolicy
78 Add to back/forward list: YES
82 Restore form state: YES
83 Restore scroll and focus state: YES
84 WF Cache policy: NSURLRequestReturnCacheDataElseLoad
85 Add to back/forward list: NO
87 Reload (meaning only the reload button):
89 Restore form state: NO
90 Restore scroll and focus state: YES
91 WF Cache policy: NSURLRequestReloadIgnoringCacheData
92 Add to back/forward list: NO
94 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 Restore form state: NO
97 Restore scroll and focus state: NO, reset to initial conditions
98 WF Cache policy: NSURLRequestReloadIgnoringCacheData
99 Add to back/forward list: NO
102 NSString *WebPageCacheEntryDateKey = @"WebPageCacheEntryDateKey";
103 NSString *WebPageCacheDataSourceKey = @"WebPageCacheDataSourceKey";
104 NSString *WebPageCacheDocumentViewKey = @"WebPageCacheDocumentViewKey";
106 @interface WebFrame (ForwardDecls)
107 - (void)_loadHTMLString:(NSString *)string baseURL:(NSURL *)URL unreachableURL:(NSURL *)unreachableURL;
108 - (NSDictionary *)_actionInformationForLoadType:(FrameLoadType)loadType isFormSubmission:(BOOL)isFormSubmission event:(NSEvent *)event originalURL:(NSURL *)URL;
110 - (void)_saveScrollPositionAndViewStateToItem:(WebHistoryItem *)item;
112 - (WebHistoryItem *)_createItem:(BOOL)useOriginal;
113 - (WebHistoryItem *)_createItemTreeWithTargetFrame:(WebFrame *)targetFrame clippedAtTarget:(BOOL)doClip;
114 - (WebHistoryItem *)_currentBackForwardListItemToResetTo;
117 @interface WebFrame (FrameTraversal)
118 - (WebFrame *)_firstChildFrame;
119 - (WebFrame *)_lastChildFrame;
120 - (unsigned)_childFrameCount;
121 - (WebFrame *)_previousSiblingFrame;
122 - (WebFrame *)_nextSiblingFrame;
123 - (WebFrame *)_traverseNextFrameStayWithin:(WebFrame *)stayWithin;
126 @interface NSView (WebFramePluginHosting)
127 - (void)setWebFrame:(WebFrame *)webFrame;
130 @interface WebFramePrivate : NSObject
133 WebFrameView *webFrameView;
135 WebFrameBridge *bridge;
136 WebHistoryItem *currentItem; // BF item for our current content
137 WebHistoryItem *provisionalItem; // BF item for where we're trying to go
138 // (only known when navigating to a pre-existing BF item)
139 WebHistoryItem *previousItem; // BF item for previous content, see _itemForSavingDocState
141 WebScriptDebugger *scriptDebugger;
142 id internalLoadDelegate;
144 NSMutableSet *plugInViews;
145 NSMutableSet *inspectors;
148 - (void)setWebFrameView:(WebFrameView *)v;
150 - (void)setProvisionalItem:(WebHistoryItem *)item;
151 - (void)setPreviousItem:(WebHistoryItem *)item;
152 - (void)setCurrentItem:(WebHistoryItem *)item;
156 @implementation WebFramePrivate
160 [webFrameView release];
162 [currentItem release];
163 [provisionalItem release];
164 [previousItem release];
166 [scriptDebugger release];
168 [inspectors release];
170 ASSERT(plugInViews == nil);
175 - (void)setWebFrameView:(WebFrameView *)v
178 [webFrameView release];
182 - (void)setProvisionalItem:(WebHistoryItem *)item
185 [provisionalItem release];
186 provisionalItem = item;
189 - (void)setPreviousItem:(WebHistoryItem *)item
192 [previousItem release];
196 - (void)setCurrentItem:(WebHistoryItem *)item
199 [currentItem release];
205 static inline WebFrame *Frame(WebCoreFrameBridge *bridge)
207 return [(WebFrameBridge *)bridge webFrame];
210 @implementation WebFrame (FrameTraversal)
212 - (WebFrame *)_firstChildFrame
214 return Frame([[self _bridge] firstChild]);
217 - (WebFrame *)_lastChildFrame
219 return Frame([[self _bridge] lastChild]);
222 - (unsigned)_childFrameCount
224 return [[self _bridge] childCount];
227 - (WebFrame *)_previousSiblingFrame;
229 return Frame([[self _bridge] previousSibling]);
232 - (WebFrame *)_nextSiblingFrame;
234 return Frame([[self _bridge] nextSibling]);
237 - (WebFrame *)_traverseNextFrameStayWithin:(WebFrame *)stayWithin
239 return Frame([[self _bridge] traverseNextFrameStayWithin:[stayWithin _bridge]]);
244 @implementation WebFrame (WebInternal)
246 - (NSURLRequest *)_webDataRequestForData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)URL unreachableURL:(NSURL *)unreachableURL
248 NSURL *fakeURL = [NSURL _web_uniqueWebDataURL];
249 NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] initWithURL:fakeURL] autorelease];
250 [request _webDataRequestSetData:data];
251 [request _webDataRequestSetEncoding:encodingName];
252 [request _webDataRequestSetBaseURL:URL];
253 [request _webDataRequestSetUnreachableURL:unreachableURL];
254 [request _webDataRequestSetMIMEType: MIMEType ? MIMEType : (NSString *)@"text/html"];
258 // helper method used in various nav cases below
259 - (void)_addBackForwardItemClippedAtTarget:(BOOL)doClip
261 if ([[self dataSource] _URLForHistory] != nil) {
262 WebHistoryItem *bfItem = [[[self webView] mainFrame] _createItemTreeWithTargetFrame:self clippedAtTarget:doClip];
263 LOG (BackForward, "for frame %@, adding item %@\n", [self name], bfItem);
264 [[[self webView] backForwardList] addItem:bfItem];
268 - (void)_addHistoryItemForFragmentScroll
270 [self _addBackForwardItemClippedAtTarget:NO];
273 - (void)_didFinishLoad
275 [_private->internalLoadDelegate webFrame:self didFinishLoadWithError:nil];
278 - (WebHistoryItem *)_createItem:(BOOL)useOriginal
280 WebDataSource *dataSrc = [self dataSource];
281 NSURLRequest *request;
282 NSURL *unreachableURL = [dataSrc unreachableURL];
285 WebHistoryItem *bfItem;
288 request = [[dataSrc _documentLoader] originalRequestCopy];
290 request = [dataSrc request];
292 if (unreachableURL != nil) {
293 URL = unreachableURL;
294 originalURL = unreachableURL;
297 originalURL = [[[dataSrc _documentLoader] originalRequestCopy] URL];
300 LOG (History, "creating item for %@", request);
302 // Frames that have never successfully loaded any content
303 // may have no URL at all. Currently our history code can't
304 // deal with such things, so we nip that in the bud here.
305 // Later we may want to learn to live with nil for URL.
306 // See bug 3368236 and related bugs for more information.
308 URL = [NSURL URLWithString:@"about:blank"];
310 if (originalURL == nil) {
311 originalURL = [NSURL URLWithString:@"about:blank"];
314 bfItem = [[[WebHistoryItem alloc] initWithURL:URL target:[self name] parent:[[self parentFrame] name] title:[dataSrc pageTitle]] autorelease];
315 [bfItem setOriginalURLString:[originalURL _web_originalDataAsString]];
317 // save form state if this is a POST
318 [bfItem _setFormInfoFromRequest:request];
320 // Set the item for which we will save document state
321 [_private setPreviousItem:_private->currentItem];
322 [_private setCurrentItem:bfItem];
328 In the case of saving state about a page with frames, we store a tree of items that mirrors the frame tree.
329 The item that was the target of the user's navigation is designated as the "targetItem".
330 When this method is called with doClip=YES we're able to create the whole tree except for the target's children,
331 which will be loaded in the future. That part of the tree will be filled out as the child loads are committed.
333 - (WebHistoryItem *)_createItemTreeWithTargetFrame:(WebFrame *)targetFrame clippedAtTarget:(BOOL)doClip
335 WebHistoryItem *bfItem = [self _createItem:[self parentFrame] ? YES : NO];
337 [self _saveScrollPositionAndViewStateToItem:_private->previousItem];
338 if (!(doClip && self == targetFrame)) {
339 // save frame state for items that aren't loading (khtml doesn't save those)
340 [_private->bridge saveDocumentState];
342 for (WebFrame *child = [self _firstChildFrame]; child; child = [child _nextSiblingFrame])
343 [bfItem addChildItem:[child _createItemTreeWithTargetFrame:targetFrame clippedAtTarget:doClip]];
345 if (self == targetFrame)
346 [bfItem setIsTargetItem:YES];
351 - (WebFrame *)_immediateChildFrameNamed:(NSString *)name
353 return Frame([[self _bridge] childFrameNamed:name]);
356 - (void)_detachChildren
358 // FIXME: is it really necessary to do this in reverse order any more?
359 WebFrame *child = [self _lastChildFrame];
360 WebFrame *prev = [child _previousSiblingFrame];
361 for (; child; child = prev, prev = [child _previousSiblingFrame])
362 [child _detachFromParent];
365 - (void)_detachFromParent
367 WebFrameBridge *bridge = [_private->bridge retain];
372 [self _saveScrollPositionAndViewStateToItem:_private->currentItem];
373 [self _detachChildren];
374 [_private->inspectors makeObjectsPerformSelector:@selector(_webFrameDetached:) withObject:self];
376 [_private->webFrameView _setWebFrame:nil]; // needed for now to be compatible w/ old behavior
378 [[self _frameLoader] clearDataSource];
379 [_private setWebFrameView:nil];
381 [self retain]; // retain self temporarily because dealloc can re-enter this method
383 [[[self parentFrame] _bridge] removeChild:bridge];
389 _private->bridge = nil;
394 - (void)_makeDocumentView
396 NSView <WebDocumentView> *documentView = [_private->webFrameView _makeDocumentViewForDataSource:[[self _frameLoader] dataSource]];
400 // FIXME: We could save work and not do this for a top-level view that is not a WebHTMLView.
401 WebFrameView *v = _private->webFrameView;
402 [_private->bridge createFrameViewWithNSView:documentView marginWidth:[v _marginWidth] marginHeight:[v _marginHeight]];
403 [self _updateBackground];
404 [_private->bridge installInFrame:[v _scrollView]];
406 // Call setDataSource on the document view after it has been placed in the view hierarchy.
407 // This what we for the top-level view, so should do this for views in subframes as well.
408 [documentView setDataSource:[[self _frameLoader] dataSource]];
411 - (void)_transitionToCommitted:(NSDictionary *)pageCache
413 ASSERT([self webView] != nil);
415 switch ([[self _frameLoader] state]) {
416 case WebFrameStateProvisional:
418 [[[[self frameView] _scrollView] contentView] setCopiesOnScroll:YES];
420 FrameLoadType loadType = [[self _frameLoader] loadType];
421 if (loadType == FrameLoadTypeForward ||
422 loadType == FrameLoadTypeBack ||
423 loadType == FrameLoadTypeIndexedBackForward ||
424 (loadType == FrameLoadTypeReload && [[[self _frameLoader] provisionalDataSource] unreachableURL] != nil))
426 // Once committed, we want to use current item for saving DocState, and
427 // the provisional item for restoring state.
428 // Note previousItem must be set before we close the URL, which will
429 // happen when the data source is made non-provisional below
430 [_private setPreviousItem:_private->currentItem];
431 ASSERT(_private->provisionalItem);
432 [_private setCurrentItem:_private->provisionalItem];
433 [_private setProvisionalItem:nil];
436 // The call to closeURL invokes the unload event handler, which can execute arbitrary
437 // JavaScript. If the script initiates a new load, we need to abandon the current load,
438 // or the two will stomp each other.
439 WebDataSource *pd = [[self _frameLoader] provisionalDataSource];
440 [[self _bridge] closeURL];
441 if (pd != [[self _frameLoader] provisionalDataSource])
444 [[self _frameLoader] commitProvisionalLoad];
446 // Handle adding the URL to the back/forward list.
447 WebDataSource *ds = [self dataSource];
448 NSString *ptitle = [ds pageTitle];
451 case FrameLoadTypeForward:
452 case FrameLoadTypeBack:
453 case FrameLoadTypeIndexedBackForward:
454 if ([[self webView] backForwardList]) {
455 // Must grab the current scroll position before disturbing it
456 [self _saveScrollPositionAndViewStateToItem:_private->previousItem];
458 // Create a document view for this document, or used the cached view.
460 NSView <WebDocumentView> *cachedView = [pageCache objectForKey: WebPageCacheDocumentViewKey];
461 ASSERT(cachedView != nil);
462 [[self frameView] _setDocumentView: cachedView];
465 [self _makeDocumentView];
469 case FrameLoadTypeReload:
470 case FrameLoadTypeSame:
471 case FrameLoadTypeReplace:
473 WebHistoryItem *currItem = _private->currentItem;
474 LOG(PageCache, "Clearing back/forward cache, %@\n", [currItem URL]);
475 [currItem setHasPageCache:NO];
476 if (loadType == FrameLoadTypeReload) {
477 [self _saveScrollPositionAndViewStateToItem:currItem];
479 NSURLRequest *request = [ds request];
480 if ([request _webDataRequestUnreachableURL] == nil) {
481 // Sometimes loading a page again leads to a different result because of cookies. Bugzilla 4072
482 [currItem setURL:[request URL]];
484 // Update the last visited time. Mostly interesting for URL autocompletion
486 NSURL *URL = [[[[ds _documentLoader] originalRequestCopy] URL] _webkit_canonicalize];
487 WebHistory *sharedHistory = [WebHistory optionalSharedHistory];
488 WebHistoryItem *oldItem = [sharedHistory itemForURL:URL];
490 [sharedHistory setLastVisitedTimeInterval:[NSDate timeIntervalSinceReferenceDate] forItem:oldItem];
492 [self _makeDocumentView];
496 // FIXME - just get rid of this case, and merge FrameLoadTypeReloadAllowingStaleData with the above case
497 case FrameLoadTypeReloadAllowingStaleData:
498 [self _makeDocumentView];
501 case FrameLoadTypeStandard:
502 if (![[ds _documentLoader] isClientRedirect]) {
503 // Add item to history and BF list
504 NSURL *URL = [ds _URLForHistory];
505 if (URL && ![URL _web_isEmpty]){
506 ASSERT([self webView]);
507 if (![[[self webView] preferences] privateBrowsingEnabled]) {
508 WebHistoryItem *entry = [[WebHistory optionalSharedHistory] addItemForURL:URL];
510 [entry setTitle: ptitle];
512 [self _addBackForwardItemClippedAtTarget:YES];
516 NSURLRequest *request = [ds request];
518 // update the URL in the BF list that we made before the redirect, unless
519 // this is alternate content for an unreachable URL (we want the BF list
520 // item to remember the unreachable URL in case it becomes reachable later)
521 if ([request _webDataRequestUnreachableURL] == nil) {
522 [_private->currentItem setURL:[request URL]];
524 // clear out the form data so we don't repost it to the wrong place if we
525 // ever go back/forward to this item
526 [_private->currentItem _setFormInfoFromRequest:request];
528 // We must also clear out form data so we don't try to restore it into the incoming page,
532 [self _makeDocumentView];
535 case FrameLoadTypeInternal:
536 // Add an item to the item tree for this frame
537 ASSERT(![[ds _documentLoader] isClientRedirect]);
538 WebFrame *parentFrame = [self parentFrame];
540 WebHistoryItem *parentItem = parentFrame->_private->currentItem;
541 // The only case where parentItem==nil should be when a parent frame loaded an
542 // empty URL, which doesn't set up a current item in that parent.
544 [parentItem addChildItem:[self _createItem: YES]];
546 // See 3556159. It's not clear if it's valid to be in FrameLoadTypeOnLoadEvent
547 // for a top-level frame, but that was a likely explanation for those crashes,
548 // so let's guard against it.
549 // ...and all FrameLoadTypeOnLoadEvent uses were folded to FrameLoadTypeInternal
550 LOG_ERROR("no parent frame in _transitionToCommitted:, loadType=%d", loadType);
552 [self _makeDocumentView];
555 // FIXME Remove this check when dummy ds is removed. An exception should be thrown
556 // if we're in the FrameLoadTypeUninitialized state.
558 ASSERT_NOT_REACHED();
562 // Tell the client we've committed this URL.
563 ASSERT([[self frameView] documentView] != nil);
564 [[self webView] _didCommitLoadForFrame: self];
565 [[[self webView] _frameLoadDelegateForwarder] webView:[self webView] didCommitLoadForFrame:self];
567 // If we have a title let the WebView know about it.
569 [[[self webView] _frameLoadDelegateForwarder] webView:[self webView]
570 didReceiveTitle:ptitle
576 case WebFrameStateCommittedPage:
577 case WebFrameStateComplete:
580 ASSERT_NOT_REACHED();
585 - (BOOL)_canCachePage
587 return [[[self webView] backForwardList] _usesPageCache];
590 - (void)_purgePageCache
592 // This method implements the rule for purging the page cache.
593 unsigned sizeLimit = [[[self webView] backForwardList] pageCacheSize];
594 unsigned pagesCached = 0;
595 WebBackForwardList *backForwardList = [[self webView] backForwardList];
596 NSArray *backList = [backForwardList backListWithLimit: 999999];
597 WebHistoryItem *oldestNonSnapbackItem = nil;
600 for (i = 0; i < [backList count]; i++){
601 WebHistoryItem *item = [backList objectAtIndex: i];
602 if ([item hasPageCache]){
603 if (oldestNonSnapbackItem == nil && ![item alwaysAttemptToUsePageCache])
604 oldestNonSnapbackItem = item;
609 // Snapback items are never directly purged here.
610 if (pagesCached >= sizeLimit) {
611 LOG(PageCache, "Purging back/forward cache, %@\n", [oldestNonSnapbackItem URL]);
612 [oldestNonSnapbackItem setHasPageCache:NO];
616 + (CFAbsoluteTime)_timeOfLastCompletedLoad
618 return [WebFrameLoader timeOfLastCompletedLoad];
621 - (BOOL)_createPageCacheForItem:(WebHistoryItem *)item
623 NSMutableDictionary *pageCache;
625 [item setHasPageCache: YES];
627 if (![_private->bridge saveDocumentToPageCache]){
628 [item setHasPageCache: NO];
632 pageCache = [item pageCache];
633 [pageCache setObject:[NSDate date] forKey: WebPageCacheEntryDateKey];
634 [pageCache setObject:[self dataSource] forKey: WebPageCacheDataSourceKey];
635 [pageCache setObject:[[self frameView] documentView] forKey: WebPageCacheDocumentViewKey];
640 - (void)_provisionalLoadStarted
642 FrameLoadType loadType = [[self _frameLoader] loadType];
644 // FIXME: This is OK as long as no one resizes the window,
645 // but in the case where someone does, it means garbage outside
646 // the occupied part of the scroll view.
647 [[[self frameView] _scrollView] setDrawsBackground:NO];
649 // Cache the page, if possible.
650 // Don't write to the cache if in the middle of a redirect, since we will want to
651 // store the final page we end up on.
652 // No point writing to the cache on a reload or loadSame, since we will just write
653 // over it again when we leave that page.
654 WebHistoryItem *item = _private->currentItem;
655 if ([self _canCachePage]
656 && [_private->bridge canCachePage]
658 && ![[self _frameLoader] isQuickRedirectComing]
659 && loadType != FrameLoadTypeReload
660 && loadType != FrameLoadTypeReloadAllowingStaleData
661 && loadType != FrameLoadTypeSame
662 && ![[self dataSource] isLoading]
663 && ![[[self _frameLoader] documentLoader] isStopping]) {
664 if ([[[self dataSource] representation] isKindOfClass:[WebHTMLRepresentation class]]) {
665 if (![item pageCache]){
666 // Add the items to this page's cache.
667 if ([self _createPageCacheForItem:item]) {
668 LOG(PageCache, "Saving page to back/forward cache, %@\n", [[self dataSource] _URL]);
670 // See if any page caches need to be purged after the addition of this
672 [self _purgePageCache];
675 LOG(PageCache, "NOT saving page to back/forward cache, unable to create items, %@\n", [[self dataSource] _URL]);
678 // Put the document into a null state, so it can be restored correctly.
679 [_private->bridge clear];
681 LOG(PageCache, "NOT saving page to back/forward cache, %@\n", [[self dataSource] _URL]);
684 // Called after we send an openURL:... down to WebCore.
687 if ([[self _frameLoader] loadType] == FrameLoadTypeStandard && [[[self dataSource] _documentLoader] isClientRedirect]) {
688 // Clear out form data so we don't try to restore it into the incoming page. Must happen after
689 // khtml has closed the URL and saved away the form state.
690 WebHistoryItem *item = _private->currentItem;
691 [item setDocumentState:nil];
692 [item setScrollPoint:NSZeroPoint];
695 if ([[self dataSource] _loadingFromPageCache]){
696 // Force a layout to update view size and thereby update scrollbars.
697 NSView <WebDocumentView> *view = [[self frameView] documentView];
698 if ([view isKindOfClass:[WebHTMLView class]]) {
699 [(WebHTMLView *)view setNeedsToApplyStyles:YES];
701 [view setNeedsLayout: YES];
704 NSArray *responses = [[[self _frameLoader] documentLoader] responses];
705 NSURLResponse *response;
706 int i, count = [responses count];
707 for (i = 0; i < count; i++){
708 response = [responses objectAtIndex: i];
709 // FIXME: If the WebKit client changes or cancels the request, this is not respected.
712 NSURLRequest *request = [[NSURLRequest alloc] initWithURL:[response URL]];
713 [self _requestFromDelegateForRequest:request identifier:&identifier error:&error];
714 [self _sendRemainingDelegateMessagesWithIdentifier:identifier response:response length:(unsigned)[response expectedContentLength] error:error];
718 // Release the resources kept in the page cache. They will be
719 // reset when we leave this page. The core side of the page cache
720 // will have already been invalidated by the bridge to prevent
721 // premature release.
722 [_private->currentItem setHasPageCache:NO];
724 [[[self _frameLoader] documentLoader] setPrimaryLoadComplete:YES];
725 // why only this frame and not parent frames?
726 [self _checkLoadCompleteForThisFrame];
730 - (void)_checkLoadCompleteForThisFrame
732 ASSERT([self webView] != nil);
734 switch ([[self _frameLoader] state]) {
735 case WebFrameStateProvisional:
737 if ([[self _frameLoader] delegateIsHandlingProvisionalLoadError])
740 WebDataSource *pd = [self provisionalDataSource];
742 LOG(Loading, "%@: checking complete in WebFrameStateProvisional", [self name]);
743 // If we've received any errors we may be stuck in the provisional state and actually
745 NSError *error = [pd _mainDocumentError];
747 // Check all children first.
748 LOG(Loading, "%@: checking complete, current state WebFrameStateProvisional", [self name]);
749 WebHistoryItem *resetItem = [self _currentBackForwardListItemToResetTo];
750 BOOL shouldReset = YES;
751 if (![pd isLoading]) {
752 LOG(Loading, "%@: checking complete in WebFrameStateProvisional, load done", [self name]);
753 [[self webView] _didFailProvisionalLoadWithError:error forFrame:self];
754 [[self _frameLoader] setDelegateIsHandlingProvisionalLoadError:YES];
755 [[[self webView] _frameLoadDelegateForwarder] webView:[self webView]
756 didFailProvisionalLoadWithError:error
758 [[self _frameLoader] setDelegateIsHandlingProvisionalLoadError:NO];
759 [_private->internalLoadDelegate webFrame:self didFinishLoadWithError:error];
761 // FIXME: can stopping loading here possibly have
762 // any effect, if isLoading is false, which it
763 // must be, to be in this branch of the if? And is it ok to just do
764 // a full-on stopLoading?
765 [[self _frameLoader] stopLoadingSubframes];
766 [[pd _documentLoader] stopLoading];
768 // Finish resetting the load state, but only if another load hasn't been started by the
769 // delegate callback.
770 if (pd == [[self _frameLoader] provisionalDataSource])
771 [[self _frameLoader] clearProvisionalLoad];
773 NSURL *unreachableURL = [[[self _frameLoader] provisionalDataSource] unreachableURL];
774 if (unreachableURL != nil && [unreachableURL isEqual:[[pd request] URL]]) {
779 if (shouldReset && resetItem != nil) {
780 [[[self webView] backForwardList] goToItem:resetItem];
786 case WebFrameStateCommittedPage:
788 WebDataSource *ds = [self dataSource];
790 //LOG(Loading, "%@: checking complete, current state WEBFRAMESTATE_COMMITTED", [self name]);
791 if (![ds isLoading]) {
792 WebFrameView *thisView = [self frameView];
793 NSView <WebDocumentView> *thisDocumentView = [thisView documentView];
794 ASSERT(thisDocumentView != nil);
796 [[self _frameLoader] markLoadComplete];
798 // FIXME: Is this subsequent work important if we already navigated away?
799 // Maybe there are bugs because of that, or extra work we can skip because
800 // the new page is ready.
802 // Tell the just loaded document to layout. This may be necessary
803 // for non-html content that needs a layout message.
804 if (!([[self dataSource] _isDocumentHTML])) {
805 [thisDocumentView setNeedsLayout:YES];
806 [thisDocumentView layout];
807 [thisDocumentView setNeedsDisplay:YES];
810 // If the user had a scroll point scroll to it. This will override
811 // the anchor point. After much discussion it was decided by folks
812 // that the user scroll point should override the anchor point.
813 if ([[self webView] backForwardList]) {
814 switch ([[self _frameLoader] loadType]) {
815 case FrameLoadTypeForward:
816 case FrameLoadTypeBack:
817 case FrameLoadTypeIndexedBackForward:
818 case FrameLoadTypeReload:
819 [self _restoreScrollPositionAndViewState];
822 case FrameLoadTypeStandard:
823 case FrameLoadTypeInternal:
824 case FrameLoadTypeReloadAllowingStaleData:
825 case FrameLoadTypeSame:
826 case FrameLoadTypeReplace:
831 ASSERT_NOT_REACHED();
836 NSError *error = [ds _mainDocumentError];
838 [[self webView] _didFailLoadWithError:error forFrame:self];
839 [[[self webView] _frameLoadDelegateForwarder] webView:[self webView]
840 didFailLoadWithError:error
842 [_private->internalLoadDelegate webFrame:self didFinishLoadWithError:error];
844 [[self webView] _didFinishLoadForFrame:self];
845 [[[self webView] _frameLoadDelegateForwarder] webView:[self webView]
846 didFinishLoadForFrame:self];
847 [_private->internalLoadDelegate webFrame:self didFinishLoadWithError:nil];
850 [[self webView] _progressCompleted: self];
857 case WebFrameStateComplete:
859 LOG(Loading, "%@: checking complete, current state WebFrameStateComplete", [self name]);
860 // Even if already complete, we might have set a previous item on a frame that
861 // didn't do any data loading on the past transaction. Make sure to clear these out.
862 [_private setPreviousItem:nil];
867 // Yikes! Serious horkage.
868 ASSERT_NOT_REACHED();
871 - (void)_handledOnloadEvents
873 [[[self webView] _frameLoadDelegateForwarder] webView:[self webView] didHandleOnloadEventsForFrame:self];
876 // Called every time a resource is completely loaded, or an error is received.
877 - (void)_checkLoadComplete
879 ASSERT([self webView] != nil);
882 for (WebFrame *frame = self; frame; frame = parent) {
884 [frame _checkLoadCompleteForThisFrame];
885 parent = [frame parentFrame];
890 - (WebFrameBridge *)_bridge
892 return _private->bridge;
895 // helper method that determines whether the subframes described by the item's subitems
896 // match our own current frameset
897 - (BOOL)_childFramesMatchItem:(WebHistoryItem *)item
899 NSArray *childItems = [item children];
900 int numChildItems = [childItems count];
901 int numChildFrames = [self _childFrameCount];
902 if (numChildFrames != numChildItems)
906 for (i = 0; i < numChildItems; i++) {
907 NSString *itemTargetName = [[childItems objectAtIndex:i] target];
908 //Search recursive here?
909 if (![self _immediateChildFrameNamed:itemTargetName])
910 return NO; // couldn't match the i'th itemTarget
913 return YES; // found matches for all itemTargets
916 // Walk the frame tree and ensure that the URLs match the URLs in the item.
917 - (BOOL)_URLsMatchItem:(WebHistoryItem *)item
919 NSURL *currentURL = [[[self dataSource] request] URL];
921 if (![[[item URL] _webkit_URLByRemovingFragment] isEqual:[currentURL _webkit_URLByRemovingFragment]])
924 NSArray *childItems = [item children];
925 WebHistoryItem *childItem;
926 WebFrame *childFrame;
927 int i, count = [childItems count];
928 for (i = 0; i < count; i++){
929 childItem = [childItems objectAtIndex:i];
930 childFrame = [self _immediateChildFrameNamed:[childItem target]];
931 if (![childFrame _URLsMatchItem: childItem])
938 // loads content into this frame, as specified by item
939 - (void)_loadItem:(WebHistoryItem *)item withLoadType:(FrameLoadType)loadType
941 NSURL *itemURL = [item URL];
942 NSURL *itemOriginalURL = [NSURL _web_URLWithDataAsString:[item originalURLString]];
943 NSURL *currentURL = [[[self dataSource] request] URL];
944 NSArray *formData = [item formData];
946 // Are we navigating to an anchor within the page?
947 // Note if we have child frames we do a real reload, since the child frames might not
948 // match our current frame structure, or they might not have the right content. We could
949 // check for all that as an additional optimization.
950 // We also do not do anchor-style navigation if we're posting a form.
952 // FIXME: These checks don't match the ones in _loadURL:referrer:loadType:target:triggeringEvent:isFormSubmission:
953 // Perhaps they should.
954 if (!formData && ![[self _frameLoader] shouldReloadForCurrent:itemURL andDestination:currentURL] && [self _URLsMatchItem:item] )
957 // FIXME: We need to normalize the code paths for anchor navigation. Something
958 // like the following line of code should be done, but also accounting for correct
959 // updates to the back/forward list and scroll position.
960 // rjw 4/9/03 See 3223929.
961 [self _loadURL:itemURL referrer:[[[self dataSource] request] HTTPReferrer] loadType:loadType target:nil triggeringEvent:nil form:nil formValues:nil];
963 // must do this maintenance here, since we don't go through a real page reload
964 [self _saveScrollPositionAndViewStateToItem:_private->currentItem];
965 // FIXME: form state might want to be saved here too
967 // We always call scrollToAnchorWithURL here, even if the URL doesn't have an
968 // anchor fragment. This is so we'll keep the WebCore Frame's URL up-to-date.
969 [_private->bridge scrollToAnchorWithURL:[item URL]];
971 // must do this maintenance here, since we don't go through a real page reload
972 [_private setCurrentItem:item];
973 [self _restoreScrollPositionAndViewState];
975 // Fake the URL change by updating the data source's request. This will no longer
976 // be necessary if we do the better fix described above.
977 [[[self _frameLoader] documentLoader] replaceRequestURLForAnchorScrollWithURL:itemURL];
979 [[[self webView] _frameLoadDelegateForwarder] webView:[self webView]
980 didChangeLocationWithinPageForFrame:self];
981 [_private->internalLoadDelegate webFrame:self didFinishLoadWithError:nil];
983 // Remember this item so we can traverse any child items as child frames load
984 [_private setProvisionalItem:item];
986 WebDataSource *newDataSource;
987 BOOL inPageCache = NO;
989 // Check if we'll be using the page cache. We only use the page cache
990 // if one exists and it is less than _backForwardCacheExpirationInterval
991 // seconds old. If the cache is expired it gets flushed here.
992 if ([item hasPageCache]){
993 NSDictionary *pageCache = [item pageCache];
994 NSDate *cacheDate = [pageCache objectForKey: WebPageCacheEntryDateKey];
995 NSTimeInterval delta = [[NSDate date] timeIntervalSinceDate: cacheDate];
997 if (delta <= [[[self webView] preferences] _backForwardCacheExpirationInterval]){
998 newDataSource = [pageCache objectForKey: WebPageCacheDataSourceKey];
999 [[self _frameLoader] loadDataSource:newDataSource withLoadType:loadType formState:nil];
1003 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]);
1004 [item setHasPageCache: NO];
1009 NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:itemURL];
1010 [self _addExtraFieldsToRequest:request mainResource:YES alwaysFromRequest:(formData != nil) ? YES : NO];
1012 // If this was a repost that failed the page cache, we might try to repost the form.
1013 NSDictionary *action;
1015 [request setHTTPMethod:@"POST"];
1016 [request _web_setHTTPReferrer:[item formReferrer]];
1017 webSetHTTPBody(request, formData);
1018 [request _web_setHTTPContentType:[item formContentType]];
1020 // Slight hack to test if the WF cache contains the page we're going to. We want
1021 // to know this before talking to the policy delegate, since it affects whether we
1022 // show the DoYouReallyWantToRepost nag.
1024 // This trick has a small bug (3123893) where we might find a cache hit, but then
1025 // have the item vanish when we try to use it in the ensuing nav. This should be
1026 // extremely rare, but in that case the user will get an error on the navigation.
1027 [request setCachePolicy:NSURLRequestReturnCacheDataDontLoad];
1028 NSURLResponse *synchResponse = nil;
1029 [NSURLConnection sendSynchronousRequest:request returningResponse:&synchResponse error:nil];
1030 if (synchResponse == nil) {
1032 [request setCachePolicy:NSURLRequestReloadIgnoringCacheData];
1033 action = [self _actionInformationForNavigationType:WebNavigationTypeFormResubmitted event:nil originalURL:itemURL];
1035 // We can use the cache, don't use navType=resubmit
1036 action = [self _actionInformationForLoadType:loadType isFormSubmission:NO event:nil originalURL:itemURL];
1040 case FrameLoadTypeReload:
1041 [request setCachePolicy:NSURLRequestReloadIgnoringCacheData];
1043 case FrameLoadTypeBack:
1044 case FrameLoadTypeForward:
1045 case FrameLoadTypeIndexedBackForward:
1046 if (![[itemURL scheme] isEqual:@"https"]) {
1047 [request setCachePolicy:NSURLRequestReturnCacheDataElseLoad];
1050 case FrameLoadTypeStandard:
1051 case FrameLoadTypeInternal:
1052 // no-op: leave as protocol default
1053 // FIXME: I wonder if we ever hit this case
1055 case FrameLoadTypeSame:
1056 case FrameLoadTypeReloadAllowingStaleData:
1058 ASSERT_NOT_REACHED();
1061 action = [self _actionInformationForLoadType:loadType isFormSubmission:NO event:nil originalURL:itemOriginalURL];
1064 [[self _frameLoader] _loadRequest:request triggeringAction:action loadType:loadType formState:nil];
1070 // The general idea here is to traverse the frame tree and the item tree in parallel,
1071 // tracking whether each frame already has the content the item requests. If there is
1072 // a match (by URL), we just restore scroll position and recurse. Otherwise we must
1073 // reload that frame, and all its kids.
1074 - (void)_recursiveGoToItem:(WebHistoryItem *)item fromItem:(WebHistoryItem *)fromItem withLoadType:(FrameLoadType)type
1076 NSURL *itemURL = [item URL];
1077 NSURL *currentURL = [[[self dataSource] request] URL];
1079 // Always reload the target frame of the item we're going to. This ensures that we will
1080 // do -some- load for the transition, which means a proper notification will be posted
1082 // The exact URL has to match, including fragment. We want to go through the _load
1083 // method, even if to do a within-page navigation.
1084 // The current frame tree and the frame tree snapshot in the item have to match.
1085 if (![item isTargetItem] &&
1086 [itemURL isEqual:currentURL] &&
1087 (([self name] == nil && [item target] == nil) ||[[self name] isEqualToString:[item target]]) &&
1088 [self _childFramesMatchItem:item])
1090 // This content is good, so leave it alone and look for children that need reloading
1092 // Save form state (works from currentItem, since prevItem is nil)
1093 ASSERT(!_private->previousItem);
1094 [_private->bridge saveDocumentState];
1095 [self _saveScrollPositionAndViewStateToItem:_private->currentItem];
1097 [_private setCurrentItem:item];
1099 // Restore form state (works from currentItem)
1100 [_private->bridge restoreDocumentState];
1101 // Restore the scroll position (taken in favor of going back to the anchor)
1102 [self _restoreScrollPositionAndViewState];
1104 NSArray *childItems = [item children];
1105 int numChildItems = childItems ? [childItems count] : 0;
1107 for (i = numChildItems - 1; i >= 0; i--) {
1108 WebHistoryItem *childItem = [childItems objectAtIndex:i];
1109 NSString *childName = [childItem target];
1110 WebHistoryItem *fromChildItem = [fromItem childItemWithName:childName];
1111 ASSERT(fromChildItem || [fromItem isTargetItem]);
1112 WebFrame *childFrame = [self _immediateChildFrameNamed:childName];
1114 [childFrame _recursiveGoToItem:childItem fromItem:fromChildItem withLoadType:type];
1117 // We need to reload the content
1118 [self _loadItem:item withLoadType:type];
1122 // Main funnel for navigating to a previous location (back/forward, non-search snap-back)
1123 // This includes recursion to handle loading into framesets properly
1124 - (void)_goToItem:(WebHistoryItem *)item withLoadType:(FrameLoadType)type
1126 ASSERT(![self parentFrame]);
1127 // shouldGoToHistoryItem is a private delegate method. This is needed to fix:
1128 // <rdar://problem/3951283> can view pages from the back/forward cache that should be disallowed by Parental Controls
1129 // Ultimately, history item navigations should go through the policy delegate. That's covered in:
1130 // <rdar://problem/3979539> back/forward cache navigations should consult policy delegate
1131 if ([[[self webView] _policyDelegateForwarder] webView:[self webView] shouldGoToHistoryItem:item]) {
1132 WebBackForwardList *backForwardList = [[self webView] backForwardList];
1133 WebHistoryItem *currItem = [backForwardList currentItem];
1134 // Set the BF cursor before commit, which lets the user quickly click back/forward again.
1135 // - plus, it only makes sense for the top level of the operation through the frametree,
1136 // as opposed to happening for some/one of the page commits that might happen soon
1137 [backForwardList goToItem:item];
1138 [self _recursiveGoToItem:item fromItem:currItem withLoadType:type];
1142 -(NSDictionary *)_actionInformationForNavigationType:(WebNavigationType)navigationType event:(NSEvent *)event originalURL:(NSURL *)URL
1144 switch ([event type]) {
1145 case NSLeftMouseDown:
1146 case NSRightMouseDown:
1147 case NSOtherMouseDown:
1149 case NSRightMouseUp:
1150 case NSOtherMouseUp:
1152 NSView *topViewInEventWindow = [[event window] contentView];
1153 NSView *viewContainingPoint = [topViewInEventWindow hitTest:[topViewInEventWindow convertPoint:[event locationInWindow] fromView:nil]];
1154 while (viewContainingPoint != nil) {
1155 if ([viewContainingPoint isKindOfClass:[WebHTMLView class]]) {
1158 viewContainingPoint = [viewContainingPoint superview];
1160 if (viewContainingPoint != nil) {
1161 NSPoint point = [viewContainingPoint convertPoint:[event locationInWindow] fromView:nil];
1162 NSDictionary *elementInfo = [(WebHTMLView *)viewContainingPoint elementAtPoint:point];
1164 return [NSDictionary dictionaryWithObjectsAndKeys:
1165 [NSNumber numberWithInt:navigationType], WebActionNavigationTypeKey,
1166 elementInfo, WebActionElementKey,
1167 [NSNumber numberWithInt:[event buttonNumber]], WebActionButtonKey,
1168 [NSNumber numberWithInt:[event modifierFlags]], WebActionModifierFlagsKey,
1169 URL, WebActionOriginalURLKey,
1177 return [NSDictionary dictionaryWithObjectsAndKeys:
1178 [NSNumber numberWithInt:navigationType], WebActionNavigationTypeKey,
1179 [NSNumber numberWithInt:[event modifierFlags]], WebActionModifierFlagsKey,
1180 URL, WebActionOriginalURLKey,
1185 -(NSDictionary *)_actionInformationForLoadType:(FrameLoadType)loadType isFormSubmission:(BOOL)isFormSubmission event:(NSEvent *)event originalURL:(NSURL *)URL
1187 WebNavigationType navType;
1188 if (isFormSubmission) {
1189 navType = WebNavigationTypeFormSubmitted;
1190 } else if (event == nil) {
1191 if (loadType == FrameLoadTypeReload) {
1192 navType = WebNavigationTypeReload;
1193 } else if (loadType == FrameLoadTypeForward
1194 || loadType == FrameLoadTypeBack
1195 || loadType == FrameLoadTypeIndexedBackForward) {
1196 navType = WebNavigationTypeBackForward;
1198 navType = WebNavigationTypeOther;
1201 navType = WebNavigationTypeLinkClicked;
1203 return [self _actionInformationForNavigationType:navType event:event originalURL:URL];
1206 - (void)_continueLoadRequestAfterNewWindowPolicy:(NSURLRequest *)request frameName:(NSString *)frameName formState:(WebFormState *)formState
1213 WebView *webView = nil;
1214 WebView *currentWebView = [self webView];
1215 id wd = [currentWebView UIDelegate];
1216 if ([wd respondsToSelector:@selector(webView:createWebViewWithRequest:)])
1217 webView = [wd webView:currentWebView createWebViewWithRequest:nil];
1219 webView = [[WebDefaultUIDelegate sharedUIDelegate] webView:currentWebView createWebViewWithRequest:nil];
1223 WebFrame *frame = [webView mainFrame];
1229 [[frame _bridge] setName:frameName];
1231 [[webView _UIDelegateForwarder] webViewShow:webView];
1233 [[frame _bridge] setOpener:[self _bridge]];
1234 [[frame _frameLoader] _loadRequest:request triggeringAction:nil loadType:FrameLoadTypeStandard formState:formState];
1242 - (void)_loadURL:(NSURL *)URL referrer:(NSString *)referrer intoChild:(WebFrame *)childFrame
1244 WebHistoryItem *parentItem = _private->currentItem;
1245 NSArray *childItems = [parentItem children];
1246 FrameLoadType loadType = [[self _frameLoader] loadType];
1247 FrameLoadType childLoadType = FrameLoadTypeInternal;
1248 WebHistoryItem *childItem = nil;
1250 // If we're moving in the backforward list, we might want to replace the content
1251 // of this child frame with whatever was there at that point.
1252 // Reload will maintain the frame contents, LoadSame will not.
1254 (loadType == FrameLoadTypeForward
1255 || loadType == FrameLoadTypeBack
1256 || loadType == FrameLoadTypeIndexedBackForward
1257 || loadType == FrameLoadTypeReload
1258 || loadType == FrameLoadTypeReloadAllowingStaleData))
1260 childItem = [parentItem childItemWithName:[childFrame name]];
1262 // Use the original URL to ensure we get all the side-effects, such as
1263 // onLoad handlers, of any redirects that happened. An example of where
1264 // this is needed is Radar 3213556.
1265 URL = [NSURL _web_URLWithDataAsString:[childItem originalURLString]];
1266 // These behaviors implied by these loadTypes should apply to the child frames
1267 childLoadType = loadType;
1269 if (loadType == FrameLoadTypeForward
1270 || loadType == FrameLoadTypeBack
1271 || loadType == FrameLoadTypeIndexedBackForward)
1273 // For back/forward, remember this item so we can traverse any child items as child frames load
1274 [childFrame->_private setProvisionalItem:childItem];
1276 // For reload, just reinstall the current item, since a new child frame was created but we won't be creating a new BF item
1277 [childFrame->_private setCurrentItem:childItem];
1282 WebArchive *archive = [[self dataSource] _popSubframeArchiveWithName:[childFrame name]];
1284 [childFrame loadArchive:archive];
1286 [[childFrame _frameLoader] loadURL:URL referrer:referrer loadType:childLoadType target:nil triggeringEvent:nil form:nil formValues:nil];
1290 - (void)_postWithURL:(NSURL *)URL referrer:(NSString *)referrer target:(NSString *)target data:(NSArray *)postData contentType:(NSString *)contentType triggeringEvent:(NSEvent *)event form:(DOMElement *)form formValues:(NSDictionary *)values
1292 // When posting, use the NSURLRequestReloadIgnoringCacheData load flag.
1293 // This prevents a potential bug which may cause a page with a form that uses itself
1294 // as an action to be returned from the cache without submitting.
1296 // FIXME: Where's the code that implements what the comment above says?
1298 NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:URL];
1299 [self _addExtraFieldsToRequest:request mainResource:YES alwaysFromRequest:YES];
1300 [request _web_setHTTPReferrer:referrer];
1301 [request setHTTPMethod:@"POST"];
1302 webSetHTTPBody(request, postData);
1303 [request _web_setHTTPContentType:contentType];
1305 NSDictionary *action = [self _actionInformationForLoadType:FrameLoadTypeStandard isFormSubmission:YES event:event originalURL:URL];
1306 WebFormState *formState = nil;
1307 if (form && values) {
1308 formState = [[WebFormState alloc] initWithForm:form values:values sourceFrame:self];
1311 if (target != nil) {
1312 WebFrame *targetFrame = [self findFrameNamed:target];
1314 if (targetFrame != nil) {
1315 [[targetFrame _frameLoader] _loadRequest:request triggeringAction:action loadType:FrameLoadTypeStandard formState:formState];
1317 [[self _frameLoader] checkNewWindowPolicyForRequest:request action:action frameName:target formState:formState andCall:self
1318 withSelector:@selector(_continueLoadRequestAfterNewWindowPolicy:frameName:formState:)];
1321 [formState release];
1325 [[self _frameLoader] _loadRequest:request triggeringAction:action loadType:FrameLoadTypeStandard formState:formState];
1328 [formState release];
1331 - (void)_setTitle:(NSString *)title
1333 [_private->currentItem setTitle:title];
1336 - (void)_saveScrollPositionAndViewStateToItem:(WebHistoryItem *)item
1339 NSView <WebDocumentView> *docView = [[self frameView] documentView];
1340 NSView *parent = [docView superview];
1341 // we might already be detached when this is called from detachFromParent, in which
1342 // case we don't want to override real data earlier gathered with (0,0)
1345 if ([docView conformsToProtocol:@protocol(_WebDocumentViewState)]) {
1346 // The view has it's own idea of where it is scrolled to, perhaps because it contains its own
1347 // ScrollView instead of using the one provided by the WebFrame
1348 point = [(id <_WebDocumentViewState>)docView scrollPoint];
1349 [item setViewState:[(id <_WebDocumentViewState>)docView viewState]];
1351 // Parent is the clipview of the DynamicScrollView the WebFrame installs
1352 ASSERT([parent isKindOfClass:[NSClipView class]]);
1353 point = [parent bounds].origin;
1355 [item setScrollPoint:point];
1360 - (void)_defersCallbacksChanged
1362 for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self])
1363 [[frame _frameLoader] defersCallbacksChanged];
1366 - (void)_viewWillMoveToHostWindow:(NSWindow *)hostWindow
1368 for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self])
1369 [[[frame frameView] documentView] viewWillMoveToHostWindow:hostWindow];
1372 - (void)_viewDidMoveToHostWindow
1374 for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self])
1375 [[[frame frameView] documentView] viewDidMoveToHostWindow];
1378 - (void)_addChild:(WebFrame *)child
1380 [[self _bridge] appendChild:[child _bridge]];
1381 [[[child dataSource] _documentLoader] setOverrideEncoding:[[[self dataSource] _documentLoader] overrideEncoding]];
1384 // If we bailed out of a b/f navigation, we might need to set the b/f cursor back to the current
1385 // item, because we optimistically move it right away at the start of the operation. But when
1386 // alternate content is loaded for an unreachableURL, we don't want to reset the b/f cursor.
1387 // Return the item that we would reset to, so we can decide later whether to actually reset.
1388 - (WebHistoryItem *)_currentBackForwardListItemToResetTo
1390 FrameLoadType loadType = [[self _frameLoader] loadType];
1391 if ((loadType == FrameLoadTypeForward
1392 || loadType == FrameLoadTypeBack
1393 || loadType == FrameLoadTypeIndexedBackForward)
1394 && self == [[self webView] mainFrame]) {
1395 return _private->currentItem;
1400 - (WebHistoryItem *)_itemForSavingDocState
1402 // For a standard page load, we will have a previous item set, which will be used to
1403 // store the form state. However, in some cases we will have no previous item, and
1404 // the current item is the right place to save the state. One example is when we
1405 // detach a bunch of frames because we are navigating from a site with frames to
1406 // another site. Another is when saving the frame state of a frame that is not the
1407 // target of the current navigation (if we even decide to save with that granularity).
1409 // Because of previousItem's "masking" of currentItem for this purpose, it's important
1410 // that previousItem be cleared at the end of a page transition. We leverage the
1411 // checkLoadComplete recursion to achieve this goal.
1413 return _private->previousItem ? _private->previousItem : _private->currentItem;
1416 - (WebHistoryItem *)_itemForRestoringDocState
1418 switch ([[self _frameLoader] loadType]) {
1419 case FrameLoadTypeReload:
1420 case FrameLoadTypeReloadAllowingStaleData:
1421 case FrameLoadTypeSame:
1422 case FrameLoadTypeReplace:
1423 // Don't restore any form state on reload or loadSame
1425 case FrameLoadTypeBack:
1426 case FrameLoadTypeForward:
1427 case FrameLoadTypeIndexedBackForward:
1428 case FrameLoadTypeInternal:
1429 case FrameLoadTypeStandard:
1430 return _private->currentItem;
1432 ASSERT_NOT_REACHED();
1436 // Walk the frame tree, telling all frames to save their form state into their current
1438 - (void)_saveDocumentAndScrollState
1440 for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self]) {
1441 [[frame _bridge] saveDocumentState];
1442 [frame _saveScrollPositionAndViewStateToItem:frame->_private->currentItem];
1446 // used to decide to use loadType=Same
1447 - (BOOL)_shouldTreatURLAsSameAsCurrent:(NSURL *)URL
1449 WebHistoryItem *item = _private->currentItem;
1450 NSString* URLString = [URL _web_originalDataAsString];
1451 return [URLString isEqual:[item URLString]] || [URLString isEqual:[item originalURLString]];
1454 - (void)_loadRequest:(NSURLRequest *)request inFrameNamed:(NSString *)frameName
1456 if (frameName == nil) {
1457 [self loadRequest:request];
1461 WebFrame *frame = [self findFrameNamed:frameName];
1464 [frame loadRequest:request];
1468 NSDictionary *action = [self _actionInformationForNavigationType:WebNavigationTypeOther event:nil originalURL:[request URL]];
1469 [[self _frameLoader] checkNewWindowPolicyForRequest:request action:action frameName:frameName formState:nil andCall:self withSelector:@selector(_continueLoadRequestAfterNewWindowPolicy:frameName:formState:)];
1472 // Return next frame to be traversed, visiting children after parent
1473 - (WebFrame *)_nextFrameWithWrap:(BOOL)wrapFlag
1475 return Frame([[self _bridge] nextFrameWithWrap:wrapFlag]);
1478 // Return previous frame to be traversed, exact reverse order of _nextFrame
1479 - (WebFrame *)_previousFrameWithWrap:(BOOL)wrapFlag
1481 return Frame([[self _bridge] previousFrameWithWrap:wrapFlag]);
1484 - (BOOL)_shouldCreateRenderers
1486 return [_private->bridge shouldCreateRenderers];
1489 - (int)_numPendingOrLoadingRequests:(BOOL)recurse
1492 return [[self _bridge] numPendingOrLoadingRequests];
1495 for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self])
1496 num += [[frame _bridge] numPendingOrLoadingRequests];
1501 - (void)_reloadForPluginChanges
1503 for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self]) {
1504 NSView <WebDocumentView> *documentView = [[frame frameView] documentView];
1505 if (([documentView isKindOfClass:[WebHTMLView class]] && [_private->bridge containsPlugins]))
1510 - (void)_attachScriptDebugger
1512 if (!_private->scriptDebugger)
1513 _private->scriptDebugger = [[WebScriptDebugger alloc] initWithWebFrame:self];
1516 - (void)_detachScriptDebugger
1518 if (_private->scriptDebugger) {
1519 id old = _private->scriptDebugger;
1520 _private->scriptDebugger = nil;
1525 - (void)_recursive_pauseNullEventsForAllNetscapePlugins
1527 for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self]) {
1528 NSView <WebDocumentView> *documentView = [[frame frameView] documentView];
1529 if ([documentView isKindOfClass:[WebHTMLView class]])
1530 [(WebHTMLView *)documentView _pauseNullEventsForAllNetscapePlugins];
1534 - (void)_recursive_resumeNullEventsForAllNetscapePlugins
1536 for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self]) {
1537 NSView <WebDocumentView> *documentView = [[frame frameView] documentView];
1538 if ([documentView isKindOfClass:[WebHTMLView class]])
1539 [(WebHTMLView *)documentView _resumeNullEventsForAllNetscapePlugins];
1543 - (void)_didReceiveServerRedirectForProvisionalLoadForFrame
1545 [[[self webView] _frameLoadDelegateForwarder] webView:[self webView]
1546 didReceiveServerRedirectForProvisionalLoadForFrame:self];
1549 - (id)_initWithWebFrameView:(WebFrameView *)fv webView:(WebView *)v bridge:(WebFrameBridge *)bridge
1551 self = [super init];
1555 _private = [[WebFramePrivate alloc] init];
1557 _private->bridge = bridge;
1560 [_private setWebFrameView:fv];
1561 [fv _setWebFrame:self];
1569 - (NSArray *)_documentViews
1571 NSMutableArray *result = [NSMutableArray array];
1572 for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self]) {
1573 id docView = [[frame frameView] documentView];
1575 [result addObject:docView];
1581 - (void)_updateBackground
1583 BOOL drawsBackground = [[self webView] drawsBackground];
1584 NSColor *backgroundColor = [[self webView] backgroundColor];
1586 for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self]) {
1587 // Never call setDrawsBackground:YES here on the scroll view or the background color will
1588 // flash between pages loads. setDrawsBackground:YES will be called in WebFrame's _frameLoadCompleted.
1589 if (!drawsBackground)
1590 [[[frame frameView] _scrollView] setDrawsBackground:NO];
1591 [[[frame frameView] _scrollView] setBackgroundColor:backgroundColor];
1592 id documentView = [[frame frameView] documentView];
1593 if ([documentView respondsToSelector:@selector(setDrawsBackground:)])
1594 [documentView setDrawsBackground:drawsBackground];
1595 if ([documentView respondsToSelector:@selector(setBackgroundColor:)])
1596 [documentView setBackgroundColor:backgroundColor];
1597 [[frame _bridge] setDrawsBackground:drawsBackground];
1598 [[frame _bridge] setBaseBackgroundColor:backgroundColor];
1602 - (void)_setInternalLoadDelegate:(id)internalLoadDelegate
1604 _private->internalLoadDelegate = internalLoadDelegate;
1607 - (id)_internalLoadDelegate
1609 return _private->internalLoadDelegate;
1612 - (NSURLRequest *)_requestFromDelegateForRequest:(NSURLRequest *)request identifier:(id *)identifier error:(NSError **)error
1614 ASSERT(request != nil);
1616 WebView *wv = [self webView];
1617 id delegate = [wv resourceLoadDelegate];
1618 id sharedDelegate = [WebDefaultResourceLoadDelegate sharedResourceLoadDelegate];
1619 WebResourceDelegateImplementationCache implementations = [wv _resourceLoadDelegateImplementations];
1620 WebDataSource *dataSource = [self dataSource];
1622 if (implementations.delegateImplementsIdentifierForRequest) {
1623 *identifier = [delegate webView:wv identifierForInitialRequest:request fromDataSource:dataSource];
1625 *identifier = [sharedDelegate webView:wv identifierForInitialRequest:request fromDataSource:dataSource];
1628 NSURLRequest *newRequest;
1629 if (implementations.delegateImplementsWillSendRequest) {
1630 newRequest = [delegate webView:wv resource:*identifier willSendRequest:request redirectResponse:nil fromDataSource:dataSource];
1632 newRequest = [sharedDelegate webView:wv resource:*identifier willSendRequest:request redirectResponse:nil fromDataSource:dataSource];
1635 if (newRequest == nil) {
1636 *error = [NSError _webKitErrorWithDomain:NSURLErrorDomain code:NSURLErrorCancelled URL:[request URL]];
1644 - (void)_sendRemainingDelegateMessagesWithIdentifier:(id)identifier response:(NSURLResponse *)response length:(unsigned)length error:(NSError *)error
1646 WebView *wv = [self webView];
1647 id delegate = [wv resourceLoadDelegate];
1648 id sharedDelegate = [WebDefaultResourceLoadDelegate sharedResourceLoadDelegate];
1649 WebResourceDelegateImplementationCache implementations = [wv _resourceLoadDelegateImplementations];
1650 WebDataSource *dataSource = [self dataSource];
1652 if (response != nil) {
1653 if (implementations.delegateImplementsDidReceiveResponse) {
1654 [delegate webView:wv resource:identifier didReceiveResponse:response fromDataSource:dataSource];
1656 [sharedDelegate webView:wv resource:identifier didReceiveResponse:response fromDataSource:dataSource];
1661 if (implementations.delegateImplementsDidReceiveContentLength) {
1662 [delegate webView:wv resource:identifier didReceiveContentLength:(WebNSUInteger)length fromDataSource:dataSource];
1664 [sharedDelegate webView:wv resource:identifier didReceiveContentLength:(WebNSUInteger)length fromDataSource:dataSource];
1669 if (implementations.delegateImplementsDidFinishLoadingFromDataSource) {
1670 [delegate webView:wv resource:identifier didFinishLoadingFromDataSource:dataSource];
1672 [sharedDelegate webView:wv resource:identifier didFinishLoadingFromDataSource:dataSource];
1674 [self _checkLoadComplete];
1676 [[wv _resourceLoadDelegateForwarder] webView:wv resource:identifier didFailLoadingWithError:error fromDataSource:dataSource];
1680 - (void)_safeLoadURL:(NSURL *)URL
1682 // Call the bridge because this is where our security checks are made.
1683 [[self _bridge] loadURL:URL
1684 referrer:[[[[self dataSource] request] URL] _web_originalDataAsString]
1688 triggeringEvent:[NSApp currentEvent]
1693 - (void)_unmarkAllMisspellings
1695 for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self])
1696 [[frame _bridge] unmarkAllMisspellings];
1699 - (BOOL)_hasSelection
1701 id documentView = [[self frameView] documentView];
1703 // optimization for common case to avoid creating potentially large selection string
1704 if ([documentView isKindOfClass:[WebHTMLView class]]) {
1705 DOMRange *selectedDOMRange = [[self _bridge] selectedDOMRange];
1706 return selectedDOMRange && ![selectedDOMRange collapsed];
1709 if ([documentView conformsToProtocol:@protocol(WebDocumentText)])
1710 return [[documentView selectedString] length] > 0;
1715 - (void)_clearSelection
1717 id documentView = [[self frameView] documentView];
1718 if ([documentView conformsToProtocol:@protocol(WebDocumentText)])
1719 [documentView deselectAll];
1724 - (BOOL)_atMostOneFrameHasSelection;
1726 // FIXME: 4186050 is one known case that makes this debug check fail
1728 for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self]) {
1729 if ([frame _hasSelection]) {
1740 - (WebFrame *)_findFrameWithSelection
1742 for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self])
1743 if ([frame _hasSelection])
1749 - (void)_clearSelectionInOtherFrames
1751 // We rely on WebDocumentSelection protocol implementors to call this method when they become first
1752 // responder. It would be nicer to just notice first responder changes here instead, but there's no
1753 // notification sent when the first responder changes in general (Radar 2573089).
1754 WebFrame *frameWithSelection = [[[self webView] mainFrame] _findFrameWithSelection];
1755 if (frameWithSelection != self)
1756 [frameWithSelection _clearSelection];
1758 // While we're in the general area of selection and frames, check that there is only one now.
1759 ASSERT([[[self webView] mainFrame] _atMostOneFrameHasSelection]);
1762 - (BOOL)_subframeIsLoading
1764 // It's most likely that the last added frame is the last to load so we walk backwards.
1765 for (WebFrame *frame = [self _lastChildFrame]; frame; frame = [frame _previousSiblingFrame])
1766 if ([[frame dataSource] isLoading] || [[frame provisionalDataSource] isLoading])
1771 - (void)_addPlugInView:(NSView *)plugInView
1773 ASSERT([plugInView respondsToSelector:@selector(setWebFrame:)]);
1774 ASSERT(![_private->plugInViews containsObject:plugInView]);
1776 if (!_private->plugInViews)
1777 _private->plugInViews = [[NSMutableSet alloc] init];
1779 [plugInView setWebFrame:self];
1780 [_private->plugInViews addObject:plugInView];
1783 - (void)_removeAllPlugInViews
1785 if (!_private->plugInViews)
1788 [_private->plugInViews makeObjectsPerformSelector:@selector(setWebFrame:) withObject:nil];
1789 [_private->plugInViews release];
1790 _private->plugInViews = nil;
1793 // This is called when leaving a page or closing the WebView
1794 - (void)_willCloseURL
1796 [self _removeAllPlugInViews];
1799 - (void)_addExtraFieldsToRequest:(NSMutableURLRequest *)request mainResource:(BOOL)mainResource alwaysFromRequest:(BOOL)f
1801 [request _web_setHTTPUserAgent:[[self webView] userAgentForURL:[request URL]]];
1803 if ([[self _frameLoader] loadType] == FrameLoadTypeReload)
1804 [request setValue:@"max-age=0" forHTTPHeaderField:@"Cache-Control"];
1806 // Don't set the cookie policy URL if it's already been set.
1807 if ([request mainDocumentURL] == nil) {
1808 if (mainResource && (self == [[self webView] mainFrame] || f))
1809 [request setMainDocumentURL:[request URL]];
1811 [request setMainDocumentURL:[[[[self webView] mainFrame] dataSource] _URL]];
1815 [request setValue:@"text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5" forHTTPHeaderField:@"Accept"];
1818 - (BOOL)_isMainFrame
1820 return self == [[self webView] mainFrame];
1823 - (void)_addInspector:(WebInspector *)inspector
1825 if (!_private->inspectors)
1826 _private->inspectors = [[NSMutableSet alloc] init];
1827 ASSERT(![_private->inspectors containsObject:inspector]);
1828 [_private->inspectors addObject:inspector];
1831 - (void)_removeInspector:(WebInspector *)inspector
1833 ASSERT([_private->inspectors containsObject:inspector]);
1834 [_private->inspectors removeObject:inspector];
1837 - (WebFrameLoader *)_frameLoader
1839 return [_private->bridge loader];
1842 - (void)_prepareForDataSourceReplacement
1844 if (![[self _frameLoader] dataSource]) {
1845 ASSERT(![self _childFrameCount]);
1849 // Make sure that any work that is triggered by resigning first reponder can get done.
1850 // The main example where this came up is the textDidEndEditing that is sent to the
1851 // FormsDelegate (3223413). We need to do this before _detachChildren, since that will
1852 // remove the views as a side-effect of freeing the bridge, at which point we can't
1853 // post the FormDelegate messages.
1855 // Note that this can also take FirstResponder away from a child of our frameView that
1856 // is not in a child frame's view. This is OK because we are in the process
1857 // of loading new content, which will blow away all editors in this top frame, and if
1858 // a non-editor is firstReponder it will not be affected by endEditingFor:.
1859 // Potentially one day someone could write a DocView whose editors were not all
1860 // replaced by loading new content, but that does not apply currently.
1861 NSView *frameView = [self frameView];
1862 NSWindow *window = [frameView window];
1863 NSResponder *firstResp = [window firstResponder];
1864 if ([firstResp isKindOfClass:[NSView class]]
1865 && [(NSView *)firstResp isDescendantOf:frameView])
1867 [window endEditingFor:firstResp];
1870 [self _detachChildren];
1873 - (void)_frameLoadCompleted
1875 NSScrollView *sv = [[self frameView] _scrollView];
1876 if ([[self webView] drawsBackground])
1877 [sv setDrawsBackground:YES];
1878 [_private setPreviousItem:nil];
1881 - (WebDataSource *)_dataSourceForDocumentLoader:(WebDocumentLoader *)loader
1883 return [(WebDocumentLoaderMac *)loader dataSource];
1886 - (WebDocumentLoader *)_createDocumentLoaderWithRequest:(NSURLRequest *)request
1888 WebDocumentLoaderMac *loader = [[WebDocumentLoaderMac alloc] initWithRequest:request];
1890 WebDataSource *dataSource = [[WebDataSource alloc] _initWithDocumentLoader:loader];
1891 [loader setDataSource:dataSource];
1892 [dataSource release];
1898 There is a race condition between the layout and load completion that affects restoring the scroll position.
1899 We try to restore the scroll position at both the first layout and upon load completion.
1901 1) If first layout happens before the load completes, we want to restore the scroll position then so that the
1902 first time we draw the page is already scrolled to the right place, instead of starting at the top and later
1903 jumping down. It is possible that the old scroll position is past the part of the doc laid out so far, in
1904 which case the restore silent fails and we will fix it in when we try to restore on doc completion.
1905 2) If the layout happens after the load completes, the attempt to restore at load completion time silently
1906 fails. We then successfully restore it when the layout happens.
1909 - (void)_restoreScrollPositionAndViewState
1911 ASSERT(_private->currentItem);
1912 NSView <WebDocumentView> *docView = [[self frameView] documentView];
1913 NSPoint point = [_private->currentItem scrollPoint];
1914 if ([docView conformsToProtocol:@protocol(_WebDocumentViewState)]) {
1915 id state = [_private->currentItem viewState];
1917 [(id <_WebDocumentViewState>)docView setViewState:state];
1920 [(id <_WebDocumentViewState>)docView setScrollPoint:point];
1922 [docView scrollPoint:point];
1928 @implementation WebFrame (WebPrivate)
1930 // FIXME: this exists only as a convenience for Safari, consider moving there
1931 - (BOOL)_isDescendantOfFrame:(WebFrame *)ancestor
1933 return [[self _bridge] isDescendantOfFrame:[ancestor _bridge]];
1936 - (void)_setShouldCreateRenderers:(BOOL)f
1938 [_private->bridge setShouldCreateRenderers:f];
1941 - (NSColor *)_bodyBackgroundColor
1943 return [_private->bridge bodyBackgroundColor];
1948 return [_private->bridge isFrameSet];
1951 - (BOOL)_firstLayoutDone
1953 return [[self _frameLoader] firstLayoutDone];
1956 - (WebFrameLoadType)_loadType
1958 return (WebFrameLoadType)[[self _frameLoader] loadType];
1963 @implementation WebFormState : NSObject
1965 - (id)initWithForm:(DOMElement *)form values:(NSDictionary *)values sourceFrame:(WebFrame *)sourceFrame
1967 self = [super init];
1971 _form = [form retain];
1972 _values = [values copy];
1973 _sourceFrame = [sourceFrame retain];
1981 [_sourceFrame release];
1985 - (DOMElement *)form
1990 - (NSDictionary *)values
1995 - (WebFrame *)sourceFrame
1997 return _sourceFrame;
2002 @implementation WebFrame
2006 return [self initWithName:nil webFrameView:nil webView:nil];
2009 // FIXME: this method can't work any more and should be marked deprecated
2010 - (id)initWithName:(NSString *)n webFrameView:(WebFrameView *)fv webView:(WebView *)v
2012 return [self _initWithWebFrameView:fv webView:v bridge:nil];
2017 ASSERT(_private->bridge == nil);
2027 ASSERT(_private->bridge == nil);
2036 return [[self _bridge] name];
2039 - (WebFrameView *)frameView
2041 return _private->webFrameView;
2044 - (WebView *)webView
2046 return [[[self _bridge] page] webView];
2049 - (DOMDocument *)DOMDocument
2051 return [[self dataSource] _isDocumentHTML] ? [_private->bridge DOMDocument] : nil;
2054 - (DOMHTMLElement *)frameElement
2056 return [[self webView] mainFrame] != self ? [_private->bridge frameElement] : nil;
2059 - (WebDataSource *)provisionalDataSource
2061 return [[self _frameLoader] provisionalDataSource];
2064 - (WebDataSource *)dataSource
2066 return [[self _frameLoader] dataSource];
2069 - (void)loadRequest:(NSURLRequest *)request
2071 // FIXME: is this the right place to reset loadType? Perhaps this should be done
2072 // after loading is finished or aborted.
2073 [[self _frameLoader] setLoadType:FrameLoadTypeStandard];
2074 [[self _frameLoader] _loadRequest:request archive:nil];
2077 - (void)_loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)URL unreachableURL:(NSURL *)unreachableURL
2079 NSURLRequest *request = [self _webDataRequestForData:data
2081 textEncodingName:encodingName
2083 unreachableURL:unreachableURL];
2084 [self loadRequest:request];
2088 - (void)loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)URL
2090 [self _loadData:data MIMEType:MIMEType textEncodingName:encodingName baseURL:URL unreachableURL:nil];
2093 - (void)_loadHTMLString:(NSString *)string baseURL:(NSURL *)URL unreachableURL:(NSURL *)unreachableURL
2095 NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
2096 [self _loadData:data MIMEType:nil textEncodingName:@"UTF-8" baseURL:URL unreachableURL:unreachableURL];
2099 - (void)loadHTMLString:(NSString *)string baseURL:(NSURL *)URL
2101 [self _loadHTMLString:string baseURL:URL unreachableURL:nil];
2104 - (void)loadAlternateHTMLString:(NSString *)string baseURL:(NSURL *)URL forUnreachableURL:(NSURL *)unreachableURL
2106 [self _loadHTMLString:string baseURL:URL unreachableURL:unreachableURL];
2109 - (void)loadArchive:(WebArchive *)archive
2111 WebResource *mainResource = [archive mainResource];
2113 NSURLRequest *request = [self _webDataRequestForData:[mainResource data]
2114 MIMEType:[mainResource MIMEType]
2115 textEncodingName:[mainResource textEncodingName]
2116 baseURL:[mainResource URL]
2117 unreachableURL:nil];
2118 [[self _frameLoader] _loadRequest:request archive:archive];
2124 [[self _frameLoader] stopLoading];
2129 [[self _frameLoader] reload];
2132 - (WebFrame *)findFrameNamed:(NSString *)name
2134 return Frame([[self _bridge] findFrameNamed:name]);
2137 - (WebFrame *)parentFrame
2139 return [[Frame([[self _bridge] parent]) retain] autorelease];
2142 - (NSArray *)childFrames
2144 NSMutableArray *children = [NSMutableArray arrayWithCapacity:[self _childFrameCount]];
2145 for (WebFrame *child = [self _firstChildFrame]; child; child = [child _nextSiblingFrame])
2146 [children addObject:child];
2153 @implementation WebFrame (WebFrameLoaderClient)
2155 - (void)_resetBackForwardList
2157 // Note this doesn't verify the current load type as a b/f operation because it is called from
2158 // a subframe in the case of a delegate bailing out of the nav before it even gets to provisional state.
2159 ASSERT(self == [[self webView] mainFrame]);
2160 WebHistoryItem *resetItem = _private->currentItem;
2162 [[[self webView] backForwardList] goToItem:resetItem];
2165 - (void)_invalidateCurrentItemPageCache
2167 // When we are pre-commit, the currentItem is where the pageCache data resides
2168 NSDictionary *pageCache = [_private->currentItem pageCache];
2170 [[self _bridge] invalidatePageCache:pageCache];
2172 // We're assuming that WebCore invalidates its pageCache state in didNotOpen:pageCache:
2173 [_private->currentItem setHasPageCache:NO];
2176 - (BOOL)_provisionalItemIsTarget
2178 return [_private->provisionalItem isTargetItem];
2181 - (BOOL)_loadProvisionalItemFromPageCache
2183 WebHistoryItem *item = _private->provisionalItem;
2184 if (![item hasPageCache])
2186 NSDictionary *pageCache = [item pageCache];
2187 if (![pageCache objectForKey:WebCorePageCacheStateKey])
2189 LOG(PageCache, "Restoring page from back/forward cache, %@", [item URL]);
2190 [[self provisionalDataSource] _loadFromPageCache:pageCache];