3b027ec995503a60f2ebc5d4c993a87bddaa7d13
[WebKit-https.git] / WebKit / WebCoreSupport / WebFrameLoaderClient.mm
1 /*
2  * Copyright (C) 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 "WebFrameLoaderClient.h"
30
31 // Terrible hack; lets us get at the WebFrame private structure.
32 #define private public
33 #import "WebFrame.h"
34 #undef private
35
36 #import "WebBackForwardList.h"
37 #import "WebChromeClient.h"
38 #import "WebDataSourceInternal.h"
39 #import "WebDefaultResourceLoadDelegate.h"
40 #import "WebDocumentInternal.h"
41 #import "WebDocumentLoaderMac.h"
42 #import "WebDownloadInternal.h"
43 #import "WebElementDictionary.h"
44 #import "WebFormDelegate.h"
45 #import "WebFrameBridge.h"
46 #import "WebFrameInternal.h"
47 #import "WebFrameLoadDelegate.h"
48 #import "WebFrameViewInternal.h"
49 #import "WebHTMLRepresentation.h"
50 #import "WebHTMLView.h"
51 #import "WebHistoryItemPrivate.h"
52 #import "WebHistoryPrivate.h"
53 #import "WebIconDatabaseInternal.h"
54 #import "WebKitErrorsPrivate.h"
55 #import "WebKitNSStringExtras.h"
56 #import "WebNSURLExtras.h"
57 #import "WebPanelAuthenticationHandler.h"
58 #import "WebPolicyDelegate.h"
59 #import "WebPreferences.h"
60 #import "WebResourceLoadDelegate.h"
61 #import "WebResourcePrivate.h"
62 #import "WebScriptDebugServerPrivate.h"
63 #import "WebUIDelegate.h"
64 #import "WebViewInternal.h"
65 #import <WebCore/Chrome.h>
66 #import <WebCore/Document.h>
67 #import <WebCore/DocumentLoader.h>
68 #import <WebCore/FormState.h>
69 #import <WebCore/FrameLoader.h>
70 #import <WebCore/FrameLoaderTypes.h>
71 #import <WebCore/FrameMac.h>
72 #import <WebCore/IconDatabase.h>
73 #import <WebCore/PageState.h>
74 #import <WebCore/FrameTree.h>
75 #import <WebCore/MouseEvent.h>
76 #import <WebCore/Page.h>
77 #import <WebCore/PlatformString.h>
78 #import <WebCore/ResourceLoader.h>
79 #import <WebCore/WebCoreFrameBridge.h>
80 #import <WebCore/WebCorePageState.h>
81 #import <WebCore/WebDataProtocol.h>
82 #import <WebKit/DOMElement.h>
83 #import <WebKitSystemInterface.h>
84 #import <wtf/PassRefPtr.h>
85
86 using namespace WebCore;
87
88 @interface WebFramePolicyListener : NSObject <WebPolicyDecisionListener, WebFormSubmissionListener>
89 {
90     Frame* m_frame;
91 }
92 - (id)initWithWebCoreFrame:(Frame*)frame;
93 - (void)invalidate;
94 @end
95
96 static inline WebView *getWebView(DocumentLoader* loader)
97 {
98     return kit(loader->frameLoader()->frame()->page());
99 }
100
101 static inline WebDataSource *dataSource(DocumentLoader* loader)
102 {
103     return loader ? static_cast<WebDocumentLoaderMac*>(loader)->dataSource() : nil;
104 }
105
106 WebFrameLoaderClient::WebFrameLoaderClient(WebFrame *webFrame)
107     : m_webFrame(webFrame)
108     , m_policyFunction(0)
109     , m_archivedResourcesDeliveryTimer(this, &WebFrameLoaderClient::deliverArchivedResources)
110 {
111 }
112
113 void WebFrameLoaderClient::detachFrameLoader()
114 {
115     delete this;
116 }
117
118 bool WebFrameLoaderClient::hasWebView() const
119 {
120     return [m_webFrame.get() webView] != nil;
121 }
122
123 bool WebFrameLoaderClient::hasFrameView() const
124 {
125     return m_webFrame->_private->webFrameView != nil;
126 }
127
128 bool WebFrameLoaderClient::hasBackForwardList() const
129 {
130     return [getWebView(m_webFrame.get()) backForwardList] != nil;
131 }
132
133 void WebFrameLoaderClient::resetBackForwardList()
134 {
135     // Note this doesn't verify the current load type as a b/f operation because it is called from
136     // a subframe in the case of a delegate bailing out of the nav before it even gets to provisional state.
137     WebFrame *mainFrame = [getWebView(m_webFrame.get()) mainFrame];
138     WebHistoryItem *resetItem = mainFrame->_private->currentItem;
139     if (resetItem)
140         [[getWebView(m_webFrame.get()) backForwardList] goToItem:resetItem];
141 }
142
143 bool WebFrameLoaderClient::provisionalItemIsTarget() const
144 {
145     return [m_webFrame->_private->provisionalItem isTargetItem];
146 }
147
148 bool WebFrameLoaderClient::loadProvisionalItemFromPageCache()
149 {
150     WebHistoryItem *item = m_webFrame->_private->provisionalItem;
151     if (![item hasPageCache])
152         return false;
153     NSDictionary *pageCache = [item pageCache];
154     if (![pageCache objectForKey:WebCorePageCacheStateKey])
155         return false;
156     [[m_webFrame.get() provisionalDataSource] _loadFromPageCache:pageCache];
157     return true;
158 }
159
160 void WebFrameLoaderClient::invalidateCurrentItemPageCache()
161 {
162     // When we are pre-commit, the currentItem is where the pageCache data resides
163     WebHistoryItem *currentItem = m_webFrame->_private->currentItem;
164     NSDictionary *pageCache = [currentItem pageCache];
165     WebCorePageState *state = [pageCache objectForKey:WebCorePageCacheStateKey];
166     WebCore::PageState* pageState = [state impl];
167
168     // FIXME: This is a grotesque hack to fix <rdar://problem/4059059> Crash in RenderFlow::detach
169     // Somehow the WebCorePageState object is not properly updated, and is holding onto a stale document.
170     // Both Xcode and FileMaker see this crash, Safari does not.
171     ASSERT(!pageState || pageState->document() == core(m_webFrame.get())->document());
172     if (pageState && pageState->document() == core(m_webFrame.get())->document())
173         pageState->clear();
174
175     // We're assuming that WebCore invalidates its pageCache state in didNotOpen:pageCache:
176     [currentItem setHasPageCache:NO];
177 }
178
179 bool WebFrameLoaderClient::privateBrowsingEnabled() const
180 {
181     return [[getWebView(m_webFrame.get()) preferences] privateBrowsingEnabled];
182 }
183
184 void WebFrameLoaderClient::makeDocumentView()
185 {
186     WebFrameView *v = m_webFrame->_private->webFrameView;
187     WebDataSource *ds = [m_webFrame.get() dataSource];
188
189     NSView <WebDocumentView> *documentView = [v _makeDocumentViewForDataSource:ds];
190     if (!documentView)
191         return;
192
193     WebFrameBridge *bridge = m_webFrame->_private->bridge;
194
195     // FIXME: We could save work and not do this for a top-level view that is not a WebHTMLView.
196     [bridge createFrameViewWithNSView:documentView marginWidth:[v _marginWidth] marginHeight:[v _marginHeight]];
197     [m_webFrame.get() _updateBackground];
198     [bridge installInFrame:[v _scrollView]];
199
200     // Call setDataSource on the document view after it has been placed in the view hierarchy.
201     // This what we for the top-level view, so should do this for views in subframes as well.
202     [documentView setDataSource:ds];
203 }
204
205 void WebFrameLoaderClient::makeRepresentation(DocumentLoader* loader)
206 {
207     [dataSource(loader) _makeRepresentation];
208 }
209
210 void WebFrameLoaderClient::setDocumentViewFromPageCache(NSDictionary *pageCache)
211 {
212     NSView <WebDocumentView> *cachedView = [pageCache objectForKey:WebPageCacheDocumentViewKey];
213     ASSERT(cachedView != nil);
214     [m_webFrame->_private->webFrameView _setDocumentView:cachedView];
215 }
216
217 void WebFrameLoaderClient::forceLayout()
218 {
219     NSView <WebDocumentView> *view = [m_webFrame->_private->webFrameView documentView];
220     if ([view isKindOfClass:[WebHTMLView class]])
221         [(WebHTMLView *)view setNeedsToApplyStyles:YES];
222     [view setNeedsLayout:YES];
223     [view layout];
224 }
225
226 void WebFrameLoaderClient::forceLayoutForNonHTML()
227 {
228     WebFrameView *thisView = m_webFrame->_private->webFrameView;
229     NSView <WebDocumentView> *thisDocumentView = [thisView documentView];
230     ASSERT(thisDocumentView != nil);
231     
232     // Tell the just loaded document to layout.  This may be necessary
233     // for non-html content that needs a layout message.
234     if (!([[m_webFrame.get() dataSource] _isDocumentHTML])) {
235         [thisDocumentView setNeedsLayout:YES];
236         [thisDocumentView layout];
237         [thisDocumentView setNeedsDisplay:YES];
238     }
239 }
240
241 void WebFrameLoaderClient::updateHistoryForCommit()
242 {
243     FrameLoadType type = core(m_webFrame.get())->loader()->loadType();
244     if (isBackForwardLoadType(type) ||
245         (type == FrameLoadTypeReload && [[m_webFrame.get() provisionalDataSource] unreachableURL] != nil)) {
246         // Once committed, we want to use current item for saving DocState, and
247         // the provisional item for restoring state.
248         // Note previousItem must be set before we close the URL, which will
249         // happen when the data source is made non-provisional below
250         [m_webFrame.get() _setPreviousItem:m_webFrame->_private->currentItem];
251         ASSERT(m_webFrame->_private->provisionalItem);
252         [m_webFrame.get() _setCurrentItem:m_webFrame->_private->provisionalItem];
253         [m_webFrame.get() _setProvisionalItem:nil];
254     }
255 }
256
257 void WebFrameLoaderClient::updateHistoryForBackForwardNavigation()
258 {
259     // Must grab the current scroll position before disturbing it
260     [m_webFrame.get() _saveScrollPositionAndViewStateToItem:m_webFrame->_private->previousItem];
261 }
262
263 void WebFrameLoaderClient::updateHistoryForReload()
264 {
265     WebHistoryItem *currItem = m_webFrame->_private->previousItem;
266     [currItem setHasPageCache:NO];
267     if (core(m_webFrame.get())->loader()->loadType() == FrameLoadTypeReload)
268         [m_webFrame.get() _saveScrollPositionAndViewStateToItem:currItem];
269     WebDataSource *dataSource = [m_webFrame.get() dataSource];
270     NSURLRequest *request = [dataSource request];
271     // Sometimes loading a page again leads to a different result because of cookies. Bugzilla 4072
272     if ([request _webDataRequestUnreachableURL] == nil)
273         [currItem setURL:[request URL]];
274     // Update the last visited time. Mostly interesting for URL autocompletion statistics.
275     NSURL *URL = [[[dataSource _documentLoader]->originalRequestCopy() URL] _webkit_canonicalize];
276     WebHistory *sharedHistory = [WebHistory optionalSharedHistory];
277     WebHistoryItem *oldItem = [sharedHistory itemForURL:URL];
278     if (oldItem)
279         [sharedHistory setLastVisitedTimeInterval:[NSDate timeIntervalSinceReferenceDate] forItem:oldItem];
280 }
281
282 void WebFrameLoaderClient::updateHistoryForStandardLoad()
283 {
284     WebDataSource *dataSource = [m_webFrame.get() dataSource];
285     if (![dataSource _documentLoader]->isClientRedirect()) {
286         NSURL *URL = [dataSource _URLForHistory];
287         if (URL && ![URL _web_isEmpty]) {
288             ASSERT(getWebView(m_webFrame.get()));
289             if (![[getWebView(m_webFrame.get()) preferences] privateBrowsingEnabled]) {
290                 WebHistoryItem *entry = [[WebHistory optionalSharedHistory] addItemForURL:URL];
291                 if ([dataSource pageTitle])
292                     [entry setTitle:[dataSource pageTitle]];                            
293             }
294             [m_webFrame.get() _addBackForwardItemClippedAtTarget:YES];
295         }
296     } else {
297         NSURLRequest *request = [dataSource request];
298         
299         // Update the URL in the BF list that we made before the redirect, unless
300         // this is alternate content for an unreachable URL (we want the BF list
301         // item to remember the unreachable URL in case it becomes reachable later).
302         if ([request _webDataRequestUnreachableURL] == nil) {
303             [m_webFrame->_private->currentItem setURL:[request URL]];
304
305             // clear out the form data so we don't repost it to the wrong place if we
306             // ever go back/forward to this item
307             [m_webFrame->_private->currentItem _setFormInfoFromRequest:request];
308
309             // We must also clear out form data so we don't try to restore it into the incoming page,
310             // see -_opened
311         }
312     }
313 }
314
315 void WebFrameLoaderClient::updateHistoryForInternalLoad()
316 {
317     // Add an item to the item tree for this frame
318     ASSERT(!core(m_webFrame.get())->loader()->documentLoader()->isClientRedirect());
319     WebFrame *parentFrame = [m_webFrame.get() parentFrame];
320     if (parentFrame) {
321         WebHistoryItem *parentItem = parentFrame->_private->currentItem;
322         // The only case where parentItem==nil should be when a parent frame loaded an
323         // empty URL, which doesn't set up a current item in that parent.
324         if (parentItem)
325             [parentItem addChildItem:[m_webFrame.get() _createItem:YES]];
326     } else {
327         // See 3556159. It's not clear if it's valid to be in WebFrameLoadTypeOnLoadEvent
328         // for a top-level frame, but that was a likely explanation for those crashes,
329         // so let's guard against it.
330         // ...and all WebFrameLoadTypeOnLoadEvent uses were folded to WebFrameLoadTypeInternal
331         LOG_ERROR("no parent frame in transitionToCommitted:, WebFrameLoadTypeInternal");
332     }
333 }
334
335 void WebFrameLoaderClient::updateHistoryAfterClientRedirect()
336 {
337     // Clear out form data so we don't try to restore it into the incoming page.  Must happen after
338     // khtml has closed the URL and saved away the form state.
339     WebHistoryItem *item = m_webFrame->_private->currentItem;
340     [item setDocumentState:nil];
341     [item setScrollPoint:NSZeroPoint];
342 }
343
344 void WebFrameLoaderClient::setCopiesOnScroll()
345 {
346     [[[m_webFrame->_private->webFrameView _scrollView] contentView] setCopiesOnScroll:YES];
347 }
348
349 LoadErrorResetToken* WebFrameLoaderClient::tokenForLoadErrorReset()
350 {
351     if (isBackForwardLoadType(core(m_webFrame.get())->loader()->loadType()) && [m_webFrame.get() _isMainFrame])
352         return (LoadErrorResetToken*)[m_webFrame->_private->currentItem retain];
353     return 0;
354 }
355
356 void WebFrameLoaderClient::resetAfterLoadError(LoadErrorResetToken* token)
357 {
358     WebHistoryItem *item = (WebHistoryItem *)token;
359     if (!item)
360         return;
361     [[getWebView(m_webFrame.get()) backForwardList] goToItem:item];
362     [item release];
363 }
364
365 void WebFrameLoaderClient::doNotResetAfterLoadError(LoadErrorResetToken* token)
366 {
367     WebHistoryItem *item = (WebHistoryItem *)token;
368     [item release];
369 }
370
371 void WebFrameLoaderClient::willCloseDocument()
372 {
373     [m_webFrame->_private->plugInViews makeObjectsPerformSelector:@selector(setWebFrame:) withObject:nil];
374     [m_webFrame->_private->plugInViews release];
375     m_webFrame->_private->plugInViews = nil;
376 }
377
378 void WebFrameLoaderClient::detachedFromParent1()
379 {
380     [m_webFrame.get() _saveScrollPositionAndViewStateToItem:m_webFrame->_private->currentItem];
381 }
382
383 void WebFrameLoaderClient::detachedFromParent2()
384 {
385     [m_webFrame->_private->inspectors makeObjectsPerformSelector:@selector(_webFrameDetached:) withObject:m_webFrame.get()];
386     [m_webFrame->_private->webFrameView _setWebFrame:nil]; // needed for now to be compatible w/ old behavior
387 }
388
389 void WebFrameLoaderClient::detachedFromParent3()
390 {
391     [m_webFrame->_private->webFrameView release];
392     m_webFrame->_private->webFrameView = nil;
393 }
394
395 void WebFrameLoaderClient::detachedFromParent4()
396 {
397     m_webFrame->_private->bridge = nil;
398 }
399
400 void WebFrameLoaderClient::loadedFromPageCache()
401 {
402     // Release the resources kept in the page cache.
403     // They will be reset when we leave this page.
404     // The WebCore side of the page cache will have already been invalidated by
405     // the bridge to prevent premature release.
406     [m_webFrame->_private->currentItem setHasPageCache:NO];
407 }
408
409 void WebFrameLoaderClient::download(NSURLConnection *connection, NSURLRequest *request,
410     NSURLResponse *response, id proxy)
411 {
412     [WebDownload _downloadWithLoadingConnection:connection
413                                         request:request
414                                        response:response
415                                        delegate:[getWebView(m_webFrame.get()) downloadDelegate]
416                                           proxy:proxy];
417 }
418
419 bool WebFrameLoaderClient::dispatchDidLoadResourceFromMemoryCache(DocumentLoader* loader, NSURLRequest *request, NSURLResponse *response, int length)
420 {
421     WebView *webView = getWebView(loader);
422     id resourceLoadDelegate = WebViewGetResourceLoadDelegate(webView);
423     WebResourceDelegateImplementationCache implementations = WebViewGetResourceLoadDelegateImplementations(webView);
424
425     if (!implementations.delegateImplementsDidLoadResourceFromMemoryCache)
426         return false;
427
428     implementations.didLoadResourceFromMemoryCacheFunc(resourceLoadDelegate, @selector(webView:didLoadResourceFromMemoryCache:response:length:fromDataSource:), webView, request, response, length, dataSource(loader));
429     return true;
430 }
431
432 id WebFrameLoaderClient::dispatchIdentifierForInitialRequest(DocumentLoader* loader, NSURLRequest *request)
433 {
434     WebView *webView = getWebView(loader);
435     id resourceLoadDelegate = WebViewGetResourceLoadDelegate(webView);
436     WebResourceDelegateImplementationCache implementations = WebViewGetResourceLoadDelegateImplementations(webView);
437
438     if (implementations.delegateImplementsIdentifierForRequest)
439         return implementations.identifierForRequestFunc(resourceLoadDelegate, @selector(webView:identifierForInitialRequest:fromDataSource:), webView, request, dataSource(loader));
440
441     return [[[NSObject alloc] init] autorelease];
442 }
443
444 NSURLRequest *WebFrameLoaderClient::dispatchWillSendRequest(DocumentLoader* loader, id identifier,
445     NSURLRequest *request, NSURLResponse *redirectResponse)
446 {
447     WebView *webView = getWebView(loader);
448     id resourceLoadDelegate = WebViewGetResourceLoadDelegate(webView);
449     WebResourceDelegateImplementationCache implementations = WebViewGetResourceLoadDelegateImplementations(webView);
450
451     if (implementations.delegateImplementsWillSendRequest)
452         return implementations.willSendRequestFunc(resourceLoadDelegate, @selector(webView:resource:willSendRequest:redirectResponse:fromDataSource:), webView, identifier, request, redirectResponse, dataSource(loader));
453
454     return request;
455 }
456
457 void WebFrameLoaderClient::dispatchDidReceiveAuthenticationChallenge(DocumentLoader* loader, id identifier,
458     NSURLAuthenticationChallenge *challenge)
459 {
460     WebView *webView = getWebView(m_webFrame.get());
461     id resourceLoadDelegate = [webView resourceLoadDelegate];
462     WebResourceDelegateImplementationCache implementations = WebViewGetResourceLoadDelegateImplementations(webView);
463
464     if (implementations.delegateImplementsDidReceiveAuthenticationChallenge) {
465         [resourceLoadDelegate webView:webView resource:identifier didReceiveAuthenticationChallenge:challenge fromDataSource:dataSource(loader)];
466         return;
467     }
468
469     NSWindow *window = [webView hostWindow] ? [webView hostWindow] : [webView window];
470     [[WebPanelAuthenticationHandler sharedHandler] startAuthentication:challenge window:window];
471 }
472
473 void WebFrameLoaderClient::dispatchDidCancelAuthenticationChallenge(DocumentLoader* loader, id identifier,
474     NSURLAuthenticationChallenge *challenge)
475 {
476     WebView *webView = getWebView(m_webFrame.get());
477     id resourceLoadDelegate = [webView resourceLoadDelegate];
478     WebResourceDelegateImplementationCache implementations = WebViewGetResourceLoadDelegateImplementations(webView);
479
480     if (implementations.delegateImplementsDidCancelAuthenticationChallenge) {
481         [resourceLoadDelegate webView:webView resource:identifier didCancelAuthenticationChallenge:challenge fromDataSource:dataSource(loader)];
482         return;
483     }
484
485     [(WebPanelAuthenticationHandler *)[WebPanelAuthenticationHandler sharedHandler] cancelAuthentication:challenge];
486 }
487
488 void WebFrameLoaderClient::dispatchDidReceiveResponse(DocumentLoader* loader, id identifier, NSURLResponse *response)
489 {
490     WebView *webView = getWebView(loader);
491     id resourceLoadDelegate = WebViewGetResourceLoadDelegate(webView);
492     WebResourceDelegateImplementationCache implementations = WebViewGetResourceLoadDelegateImplementations(webView);
493
494     if (implementations.delegateImplementsDidReceiveResponse)
495         implementations.didReceiveResponseFunc(resourceLoadDelegate, @selector(webView:resource:didReceiveResponse:fromDataSource:), webView, identifier, response, dataSource(loader));
496 }
497
498 void WebFrameLoaderClient::dispatchDidReceiveContentLength(DocumentLoader* loader, id identifier, int lengthReceived)
499 {
500     WebView *webView = getWebView(loader);
501     id resourceLoadDelegate = WebViewGetResourceLoadDelegate(webView);
502     WebResourceDelegateImplementationCache implementations = WebViewGetResourceLoadDelegateImplementations(webView);
503
504     if (implementations.delegateImplementsDidReceiveContentLength)
505         implementations.didReceiveContentLengthFunc(resourceLoadDelegate, @selector(webView:resource:didReceiveContentLength:fromDataSource:), webView, identifier, (WebNSUInteger)lengthReceived, dataSource(loader));
506 }
507
508 void WebFrameLoaderClient::dispatchDidFinishLoading(DocumentLoader* loader, id identifier)
509 {
510     WebView *webView = getWebView(loader);
511     id resourceLoadDelegate = WebViewGetResourceLoadDelegate(webView);
512     WebResourceDelegateImplementationCache implementations = WebViewGetResourceLoadDelegateImplementations(webView);
513     
514     if (implementations.delegateImplementsDidFinishLoadingFromDataSource)
515         implementations.didFinishLoadingFromDataSourceFunc(resourceLoadDelegate, @selector(webView:resource:didFinishLoadingFromDataSource:), webView, identifier, dataSource(loader));
516 }
517
518 void WebFrameLoaderClient::dispatchDidFailLoading(DocumentLoader* loader, id identifier, NSError *error)
519 {
520     WebView *webView = getWebView(m_webFrame.get());
521     [[webView _resourceLoadDelegateForwarder] webView:webView resource:identifier didFailLoadingWithError:error fromDataSource:dataSource(loader)];
522 }
523
524 void WebFrameLoaderClient::dispatchDidHandleOnloadEvents()
525 {
526     WebView *webView = getWebView(m_webFrame.get());
527     [[webView _frameLoadDelegateForwarder] webView:webView didHandleOnloadEventsForFrame:m_webFrame.get()];
528 }
529
530 void WebFrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad()
531 {
532     WebView *webView = getWebView(m_webFrame.get());
533     [[webView _frameLoadDelegateForwarder] webView:webView
534        didReceiveServerRedirectForProvisionalLoadForFrame:m_webFrame.get()];
535 }
536
537 void WebFrameLoaderClient::dispatchDidCancelClientRedirect()
538 {
539     WebView *webView = getWebView(m_webFrame.get());
540     [[webView _frameLoadDelegateForwarder] webView:webView didCancelClientRedirectForFrame:m_webFrame.get()];
541 }
542
543 void WebFrameLoaderClient::dispatchWillPerformClientRedirect(const KURL& URL, double delay, double fireDate)
544 {
545     WebView *webView = getWebView(m_webFrame.get());
546     [[webView _frameLoadDelegateForwarder] webView:webView
547                          willPerformClientRedirectToURL:URL.getNSURL()
548                                                   delay:delay
549                                                fireDate:[NSDate dateWithTimeIntervalSince1970:fireDate]
550                                                forFrame:m_webFrame.get()];
551 }
552
553 void WebFrameLoaderClient::dispatchDidChangeLocationWithinPage()
554 {
555     WebView *webView = getWebView(m_webFrame.get());   
556     [[webView _frameLoadDelegateForwarder] webView:webView didChangeLocationWithinPageForFrame:m_webFrame.get()];
557 }
558
559 void WebFrameLoaderClient::dispatchWillClose()
560 {
561     WebView *webView = getWebView(m_webFrame.get());   
562     [[webView _frameLoadDelegateForwarder] webView:webView willCloseFrame:m_webFrame.get()];
563 }
564
565 void WebFrameLoaderClient::dispatchDidReceiveIcon()
566 {
567     WebView *webView = getWebView(m_webFrame.get());   
568     ASSERT([m_webFrame.get() _isMainFrame]);
569     // FIXME: This willChangeValueForKey call is too late, because the icon has already changed by now.
570     [webView _willChangeValueForKey:_WebMainFrameIconKey];
571     id delegate = [webView frameLoadDelegate];
572     if ([delegate respondsToSelector:@selector(webView:didReceiveIcon:forFrame:)]) {
573         Image* image = IconDatabase::sharedIconDatabase()->
574             iconForPageURL(core(m_webFrame.get())->loader()->url().url(), IntSize(16, 16));
575         NSImage *icon = webGetNSImage(image, NSMakeSize(16, 16));
576         if (icon)
577             [delegate webView:webView didReceiveIcon:icon forFrame:m_webFrame.get()];
578     }
579     [webView _didChangeValueForKey:_WebMainFrameIconKey];
580 }
581
582 void WebFrameLoaderClient::dispatchDidStartProvisionalLoad()
583 {
584     WebView *webView = getWebView(m_webFrame.get());   
585     [webView _didStartProvisionalLoadForFrame:m_webFrame.get()];
586     [[webView _frameLoadDelegateForwarder] webView:webView didStartProvisionalLoadForFrame:m_webFrame.get()];    
587 }
588
589 void WebFrameLoaderClient::dispatchDidReceiveTitle(const String& title)
590 {
591     WebView *webView = getWebView(m_webFrame.get());   
592     [[webView _frameLoadDelegateForwarder] webView:webView didReceiveTitle:title forFrame:m_webFrame.get()];
593 }
594
595 void WebFrameLoaderClient::dispatchDidCommitLoad()
596 {
597     // Tell the client we've committed this URL.
598     ASSERT([m_webFrame->_private->webFrameView documentView] != nil);
599
600     WebView *webView = getWebView(m_webFrame.get());   
601     [webView _didCommitLoadForFrame:m_webFrame.get()];
602     [[webView _frameLoadDelegateForwarder] webView:webView didCommitLoadForFrame:m_webFrame.get()];
603 }
604
605 void WebFrameLoaderClient::dispatchDidFailProvisionalLoad(NSError *error)
606 {
607     WebView *webView = getWebView(m_webFrame.get());   
608     [webView _didFailProvisionalLoadWithError:error forFrame:m_webFrame.get()];
609     [[webView _frameLoadDelegateForwarder] webView:webView didFailProvisionalLoadWithError:error forFrame:m_webFrame.get()];
610     [m_webFrame->_private->internalLoadDelegate webFrame:m_webFrame.get() didFinishLoadWithError:error];
611 }
612
613 void WebFrameLoaderClient::dispatchDidFailLoad(NSError *error)
614 {
615     WebView *webView = getWebView(m_webFrame.get());   
616     [webView _didFailLoadWithError:error forFrame:m_webFrame.get()];
617     [[webView _frameLoadDelegateForwarder] webView:webView didFailLoadWithError:error forFrame:m_webFrame.get()];
618     [m_webFrame->_private->internalLoadDelegate webFrame:m_webFrame.get() didFinishLoadWithError:error];
619 }
620
621 void WebFrameLoaderClient::dispatchDidFinishLoad()
622 {
623     WebView *webView = getWebView(m_webFrame.get());   
624     [webView _didFinishLoadForFrame:m_webFrame.get()];
625     [[webView _frameLoadDelegateForwarder] webView:webView didFinishLoadForFrame:m_webFrame.get()];
626     [m_webFrame->_private->internalLoadDelegate webFrame:m_webFrame.get() didFinishLoadWithError:nil];
627 }
628
629 void WebFrameLoaderClient::dispatchDidFirstLayout()
630 {
631     WebView *webView = getWebView(m_webFrame.get());
632     [[webView _frameLoadDelegateForwarder] webView:webView didFirstLayoutInFrame:m_webFrame.get()];
633 }
634
635 Frame* WebFrameLoaderClient::dispatchCreatePage(NSURLRequest *request)
636 {
637     WebView *currentWebView = getWebView(m_webFrame.get());
638     id wd = [currentWebView UIDelegate];
639     if ([wd respondsToSelector:@selector(webView:createWebViewWithRequest:)])
640         return core([[wd webView:currentWebView createWebViewWithRequest:request] mainFrame]);
641     return 0;
642 }
643
644 void WebFrameLoaderClient::dispatchShow()
645 {
646     WebView *webView = getWebView(m_webFrame.get());
647     [[webView _UIDelegateForwarder] webViewShow:webView];
648 }
649
650 void WebFrameLoaderClient::dispatchDecidePolicyForMIMEType(FramePolicyFunction function,
651     const String& MIMEType, NSURLRequest *request)
652 {
653     WebView *webView = getWebView(m_webFrame.get());
654
655     [[webView _policyDelegateForwarder] webView:webView
656                         decidePolicyForMIMEType:MIMEType
657                                         request:request
658                                           frame:m_webFrame.get()
659                                decisionListener:setUpPolicyListener(function).get()];
660 }
661
662 void WebFrameLoaderClient::dispatchDecidePolicyForNewWindowAction(FramePolicyFunction function,
663     const NavigationAction& action, NSURLRequest *request, const String& frameName)
664 {
665     WebView *webView = getWebView(m_webFrame.get());
666     [[webView _policyDelegateForwarder] webView:webView
667             decidePolicyForNewWindowAction:actionDictionary(action)
668                                    request:request
669                               newFrameName:frameName
670                           decisionListener:setUpPolicyListener(function).get()];
671 }
672
673 void WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction(FramePolicyFunction function,
674     const NavigationAction& action, NSURLRequest *request)
675 {
676     WebView *webView = getWebView(m_webFrame.get());
677     [[webView _policyDelegateForwarder] webView:webView
678                 decidePolicyForNavigationAction:actionDictionary(action)
679                                         request:request
680                                           frame:m_webFrame.get()
681                                decisionListener:setUpPolicyListener(function).get()];
682 }
683
684 void WebFrameLoaderClient::cancelPolicyCheck()
685 {
686     [m_policyListener.get() invalidate];
687     m_policyListener = nil;
688     m_policyFunction = 0;
689 }
690
691 void WebFrameLoaderClient::dispatchUnableToImplementPolicy(NSError *error)
692 {
693     WebView *webView = getWebView(m_webFrame.get());
694     [[webView _policyDelegateForwarder] webView:webView
695         unableToImplementPolicyWithError:error frame:m_webFrame.get()];    
696 }
697
698 void WebFrameLoaderClient::dispatchWillSubmitForm(FramePolicyFunction function, PassRefPtr<FormState> formState)
699 {
700     id <WebFormDelegate> formDelegate = [getWebView(m_webFrame.get()) _formDelegate];
701     if (!formDelegate) {
702         (core(m_webFrame.get())->loader()->*function)(PolicyUse);
703         return;
704     }
705
706     NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] initWithCapacity:formState->values().size()];
707     HashMap<String, String>::const_iterator end = formState->values().end();
708     for (HashMap<String, String>::const_iterator it = formState->values().begin(); it != end; ++it)
709         if (!it->first.isNull() && !it->second.isNull())
710             [dictionary setObject:it->second forKey:it->first];
711
712     [formDelegate frame:m_webFrame.get()
713             sourceFrame:kit(formState->sourceFrame())
714          willSubmitForm:kit(formState->form())
715              withValues:dictionary
716      submissionListener:setUpPolicyListener(function).get()];
717
718     [dictionary release];
719 }
720
721 void WebFrameLoaderClient::dispatchDidLoadMainResource(DocumentLoader* loader)
722 {
723     if ([WebScriptDebugServer listenerCount])
724         [[WebScriptDebugServer sharedScriptDebugServer] webView:getWebView(m_webFrame.get())
725             didLoadMainResourceForDataSource:dataSource(loader)];
726 }
727
728 void WebFrameLoaderClient::clearLoadingFromPageCache(DocumentLoader* loader)
729 {
730     [dataSource(loader) _setLoadingFromPageCache:NO];
731 }
732
733 bool WebFrameLoaderClient::isLoadingFromPageCache(DocumentLoader* loader)
734 {
735     return [dataSource(loader) _loadingFromPageCache];
736 }
737
738 void WebFrameLoaderClient::revertToProvisionalState(DocumentLoader* loader)
739 {
740     [dataSource(loader) _revertToProvisionalState];
741 }
742
743 void WebFrameLoaderClient::setMainDocumentError(DocumentLoader* loader, NSError *error)
744 {
745     [dataSource(loader) _setMainDocumentError:error];
746 }
747
748 void WebFrameLoaderClient::clearUnarchivingState(DocumentLoader* loader)
749 {
750     [dataSource(loader) _clearUnarchivingState];
751 }
752
753 void WebFrameLoaderClient::progressStarted()
754 {
755     [getWebView(m_webFrame.get()) _progressStarted:m_webFrame.get()];
756 }
757
758 void WebFrameLoaderClient::progressCompleted()
759 {
760     [getWebView(m_webFrame.get()) _progressCompleted:m_webFrame.get()];
761 }
762
763 void WebFrameLoaderClient::incrementProgress(id identifier, NSURLResponse *response)
764 {
765     [getWebView(m_webFrame.get()) _incrementProgressForIdentifier:identifier response:response];
766 }
767
768 void WebFrameLoaderClient::incrementProgress(id identifier, NSData *data)
769 {
770     [getWebView(m_webFrame.get()) _incrementProgressForIdentifier:identifier data:data];
771 }
772
773 void WebFrameLoaderClient::completeProgress(id identifier)
774 {
775     [getWebView(m_webFrame.get()) _completeProgressForIdentifier:identifier];
776 }
777
778 void WebFrameLoaderClient::setMainFrameDocumentReady(bool ready)
779 {
780     [getWebView(m_webFrame.get()) setMainFrameDocumentReady:ready];
781 }
782
783 void WebFrameLoaderClient::startDownload(NSURLRequest *request)
784 {
785     // FIXME: Should download full request.
786     [getWebView(m_webFrame.get()) _downloadURL:[request URL]];
787 }
788
789 void WebFrameLoaderClient::willChangeTitle(DocumentLoader* loader)
790 {
791     // FIXME: Should do this only in main frame case, right?
792     [getWebView(m_webFrame.get()) _willChangeValueForKey:_WebMainFrameTitleKey];
793 }
794
795 void WebFrameLoaderClient::didChangeTitle(DocumentLoader* loader)
796 {
797     // FIXME: Should do this only in main frame case, right?
798     [getWebView(m_webFrame.get()) _didChangeValueForKey:_WebMainFrameTitleKey];
799 }
800
801 void WebFrameLoaderClient::committedLoad(DocumentLoader* loader, NSData *data)
802 {
803     [dataSource(loader) _receivedData:data];
804 }
805
806 void WebFrameLoaderClient::finishedLoading(DocumentLoader* loader)
807 {
808     [dataSource(loader) _finishedLoading];
809 }
810
811 void WebFrameLoaderClient::finalSetupForReplace(DocumentLoader* loader)
812 {
813     [dataSource(loader) _clearUnarchivingState];
814 }
815
816 NSError *WebFrameLoaderClient::cancelledError(NSURLRequest *request)
817 {
818     return [NSError _webKitErrorWithDomain:NSURLErrorDomain code:NSURLErrorCancelled URL:[request URL]];
819 }
820
821 NSError *WebFrameLoaderClient::cannotShowURLError(NSURLRequest *request)
822 {
823     return [NSError _webKitErrorWithDomain:WebKitErrorDomain code:WebKitErrorCannotShowURL URL:[request URL]];
824 }
825
826 NSError *WebFrameLoaderClient::interruptForPolicyChangeError(NSURLRequest *request)
827 {
828     return [NSError _webKitErrorWithDomain:WebKitErrorDomain code:WebKitErrorFrameLoadInterruptedByPolicyChange URL:[request URL]];
829 }
830
831 NSError *WebFrameLoaderClient::cannotShowMIMETypeError(NSURLResponse *response)
832 {
833     return [NSError _webKitErrorWithDomain:NSURLErrorDomain code:WebKitErrorCannotShowMIMEType URL:[response URL]];    
834 }
835
836 NSError *WebFrameLoaderClient::fileDoesNotExistError(NSURLResponse *response)
837 {
838     return [NSError _webKitErrorWithDomain:NSURLErrorDomain code:NSURLErrorFileDoesNotExist URL:[response URL]];    
839 }
840
841 bool WebFrameLoaderClient::shouldFallBack(NSError *error)
842 {
843     // FIXME: Needs to check domain.
844     // FIXME: WebKitErrorPlugInWillHandleLoad is a workaround for the cancel we do to prevent
845     // loading plugin content twice.  See <rdar://problem/4258008>
846     return [error code] != NSURLErrorCancelled && [error code] != WebKitErrorPlugInWillHandleLoad;
847 }
848
849 void WebFrameLoaderClient::setDefersLoading(bool defers)
850 {
851     if (!defers)
852         deliverArchivedResourcesAfterDelay();
853 }
854
855 bool WebFrameLoaderClient::willUseArchive(ResourceLoader* loader, NSURLRequest *request, NSURL *originalURL) const
856 {
857     if (![[request URL] isEqual:originalURL])
858         return false;
859     if (!canUseArchivedResource(request))
860         return false;
861     WebResource *resource = [dataSource(core(m_webFrame.get())->loader()->activeDocumentLoader()) _archivedSubresourceForURL:originalURL];
862     if (!resource)
863         return false;
864     if (!canUseArchivedResource([resource _response]))
865         return false;
866     m_pendingArchivedResources.set(loader, resource);
867     // Deliver the resource after a delay because callers don't expect to receive callbacks while calling this method.
868     deliverArchivedResourcesAfterDelay();
869     return true;
870 }
871
872 bool WebFrameLoaderClient::isArchiveLoadPending(ResourceLoader* loader) const
873 {
874     return m_pendingArchivedResources.contains(loader);
875 }
876
877 void WebFrameLoaderClient::cancelPendingArchiveLoad(ResourceLoader* loader)
878 {
879     if (m_pendingArchivedResources.isEmpty())
880         return;
881     m_pendingArchivedResources.remove(loader);
882     if (m_pendingArchivedResources.isEmpty())
883         m_archivedResourcesDeliveryTimer.stop();
884 }
885
886 void WebFrameLoaderClient::clearArchivedResources()
887 {
888     m_pendingArchivedResources.clear();
889     m_archivedResourcesDeliveryTimer.stop();
890 }
891
892 bool WebFrameLoaderClient::canHandleRequest(NSURLRequest *request) const
893 {
894     return [WebView _canHandleRequest:request];
895 }
896
897 bool WebFrameLoaderClient::canShowMIMEType(const String& MIMEType) const
898 {
899     return [WebView canShowMIMEType:MIMEType];
900 }
901
902 bool WebFrameLoaderClient::representationExistsForURLScheme(const String& URLScheme) const
903 {
904     return [WebView _representationExistsForURLScheme:URLScheme];
905 }
906
907 String WebFrameLoaderClient::generatedMIMETypeForURLScheme(const String& URLScheme) const
908 {
909     return [WebView _generatedMIMETypeForURLScheme:URLScheme];
910 }
911
912 void WebFrameLoaderClient::frameLoadCompleted()
913 {
914     // Note: Can be called multiple times.
915     // Even if already complete, we might have set a previous item on a frame that
916     // didn't do any data loading on the past transaction. Make sure to clear these out.
917     NSScrollView *sv = [m_webFrame->_private->webFrameView _scrollView];
918     if ([getWebView(m_webFrame.get()) drawsBackground])
919         [sv setDrawsBackground:YES];
920     [m_webFrame.get() _setPreviousItem:nil];
921 }
922
923 /*
924  There is a race condition between the layout and load completion that affects restoring the scroll position.
925  We try to restore the scroll position at both the first layout and upon load completion.
926  
927  1) If first layout happens before the load completes, we want to restore the scroll position then so that the
928  first time we draw the page is already scrolled to the right place, instead of starting at the top and later
929  jumping down.  It is possible that the old scroll position is past the part of the doc laid out so far, in
930  which case the restore silent fails and we will fix it in when we try to restore on doc completion.
931  2) If the layout happens after the load completes, the attempt to restore at load completion time silently
932  fails.  We then successfully restore it when the layout happens.
933 */
934 void WebFrameLoaderClient::restoreScrollPositionAndViewState()
935 {
936     ASSERT(m_webFrame->_private->currentItem);
937     NSView <WebDocumentView> *docView = [m_webFrame->_private->webFrameView documentView];
938     NSPoint point = [m_webFrame->_private->currentItem scrollPoint];
939     if ([docView conformsToProtocol:@protocol(_WebDocumentViewState)]) {        
940         id state = [m_webFrame->_private->currentItem viewState];
941         if (state) {
942             [(id <_WebDocumentViewState>)docView setViewState:state];
943         }
944         
945         [(id <_WebDocumentViewState>)docView setScrollPoint:point];
946     } else {
947         [docView scrollPoint:point];
948     }
949 }
950
951 void WebFrameLoaderClient::provisionalLoadStarted()
952 {
953     FrameLoadType loadType = core(m_webFrame.get())->loader()->loadType();
954     
955     // FIXME: This is OK as long as no one resizes the window,
956     // but in the case where someone does, it means garbage outside
957     // the occupied part of the scroll view.
958     [[m_webFrame->_private->webFrameView _scrollView] setDrawsBackground:NO];
959     
960     // Cache the page, if possible.
961     // Don't write to the cache if in the middle of a redirect, since we will want to
962     // store the final page we end up on.
963     // No point writing to the cache on a reload or loadSame, since we will just write
964     // over it again when we leave that page.
965     WebHistoryItem *item = m_webFrame->_private->currentItem;
966     if ([m_webFrame.get() _canCachePage]
967         && item
968         && !core(m_webFrame.get())->loader()->isQuickRedirectComing()
969         && loadType != FrameLoadTypeReload 
970         && loadType != FrameLoadTypeReloadAllowingStaleData
971         && loadType != FrameLoadTypeSame
972         && ![[m_webFrame.get() dataSource] isLoading]
973         && !core(m_webFrame.get())->loader()->documentLoader()->isStopping()) {
974         if ([[[m_webFrame.get() dataSource] representation] isKindOfClass:[WebHTMLRepresentation class]]) {
975             if (![item pageCache]) {
976                 // Add the items to this page's cache.
977                 if (createPageCache(item))
978                     // See if any page caches need to be purged after the addition of this new page cache.
979                     [m_webFrame.get() _purgePageCache];
980             }
981         } else
982             // Put the document into a null state, so it can be restored correctly.
983             core(m_webFrame.get())->loader()->clear();
984     }
985 }
986
987 bool WebFrameLoaderClient::shouldTreatURLAsSameAsCurrent(const KURL& URL) const
988 {
989     WebHistoryItem *item = m_webFrame->_private->currentItem;
990     NSString* URLString = [URL.getNSURL() _web_originalDataAsString];
991     return [URLString isEqual:[item URLString]] || [URLString isEqual:[item originalURLString]];
992 }
993
994 void WebFrameLoaderClient::addHistoryItemForFragmentScroll()
995 {
996     [m_webFrame.get() _addBackForwardItemClippedAtTarget:NO];
997 }
998
999 void WebFrameLoaderClient::didFinishLoad()
1000 {
1001     [m_webFrame->_private->internalLoadDelegate webFrame:m_webFrame.get() didFinishLoadWithError:nil];    
1002 }
1003
1004 void WebFrameLoaderClient::prepareForDataSourceReplacement()
1005 {
1006     if (![m_webFrame.get() dataSource]) {
1007         ASSERT(!core(m_webFrame.get())->tree()->childCount());
1008         return;
1009     }
1010     
1011     // Make sure that any work that is triggered by resigning first reponder can get done.
1012     // The main example where this came up is the textDidEndEditing that is sent to the
1013     // FormsDelegate (3223413).  We need to do this before _detachChildren, since that will
1014     // remove the views as a side-effect of freeing the bridge, at which point we can't
1015     // post the FormDelegate messages.
1016     //
1017     // Note that this can also take FirstResponder away from a child of our frameView that
1018     // is not in a child frame's view.  This is OK because we are in the process
1019     // of loading new content, which will blow away all editors in this top frame, and if
1020     // a non-editor is firstReponder it will not be affected by endEditingFor:.
1021     // Potentially one day someone could write a DocView whose editors were not all
1022     // replaced by loading new content, but that does not apply currently.
1023     NSView *frameView = m_webFrame->_private->webFrameView;
1024     NSWindow *window = [frameView window];
1025     NSResponder *firstResp = [window firstResponder];
1026     if ([firstResp isKindOfClass:[NSView class]] && [(NSView *)firstResp isDescendantOf:frameView])
1027         [window endEditingFor:firstResp];
1028     
1029     core(m_webFrame.get())->loader()->detachChildren();
1030 }
1031
1032 PassRefPtr<DocumentLoader> WebFrameLoaderClient::createDocumentLoader(NSURLRequest *request)
1033 {
1034     RefPtr<WebDocumentLoaderMac> loader = new WebDocumentLoaderMac(request);
1035
1036     WebDataSource *dataSource = [[WebDataSource alloc] _initWithDocumentLoader:loader.get()];
1037     loader->setDataSource(dataSource);
1038     [dataSource release];
1039
1040     return loader.release();
1041 }
1042
1043 void WebFrameLoaderClient::setTitle(const String& title, const KURL& URL)
1044 {
1045     NSString *titleNSString = title;
1046     [[[WebHistory optionalSharedHistory] itemForURL:URL.getNSURL()] setTitle:titleNSString];
1047     [m_webFrame->_private->currentItem setTitle:titleNSString];
1048 }
1049
1050 // The following 2 functions are copied from [NSHTTPURLProtocol _cachedResponsePassesValidityChecks] and modified for our needs.
1051 // FIXME: It would be nice to eventually to share this logic somehow.
1052 bool WebFrameLoaderClient::canUseArchivedResource(NSURLRequest *request) const
1053 {
1054     NSURLRequestCachePolicy policy = [request cachePolicy];
1055     if (policy == NSURLRequestReturnCacheDataElseLoad)
1056         return true;
1057     if (policy == NSURLRequestReturnCacheDataDontLoad)
1058         return true;
1059     if (policy == NSURLRequestReloadIgnoringCacheData)
1060         return false;
1061     if ([request valueForHTTPHeaderField:@"must-revalidate"] != nil)
1062         return false;
1063     if ([request valueForHTTPHeaderField:@"proxy-revalidate"] != nil)
1064         return false;
1065     if ([request valueForHTTPHeaderField:@"If-Modified-Since"] != nil)
1066         return false;
1067     if ([request valueForHTTPHeaderField:@"Cache-Control"] != nil)
1068         return false;
1069     if ([@"POST" _webkit_isCaseInsensitiveEqualToString:[request HTTPMethod]])
1070         return false;
1071     return true;
1072 }
1073
1074 bool WebFrameLoaderClient::canUseArchivedResource(NSURLResponse *response) const
1075 {
1076     if (WKGetNSURLResponseMustRevalidate(response))
1077         return false;
1078     if (WKGetNSURLResponseCalculatedExpiration(response) - CFAbsoluteTimeGetCurrent() < 1)
1079         return false;
1080     return true;
1081 }
1082
1083 void WebFrameLoaderClient::deliverArchivedResourcesAfterDelay() const
1084 {
1085     if (m_pendingArchivedResources.isEmpty())
1086         return;
1087     if (core(m_webFrame.get())->page()->defersLoading())
1088         return;
1089     if (!m_archivedResourcesDeliveryTimer.isActive())
1090         m_archivedResourcesDeliveryTimer.startOneShot(0);
1091 }
1092
1093 void WebFrameLoaderClient::deliverArchivedResources(Timer<WebFrameLoaderClient>*)
1094 {
1095     if (m_pendingArchivedResources.isEmpty())
1096         return;
1097     if (core(m_webFrame.get())->page()->defersLoading())
1098         return;
1099
1100     const ResourceMap copy = m_pendingArchivedResources;
1101     m_pendingArchivedResources.clear();
1102
1103     ResourceMap::const_iterator end = copy.end();
1104     for (ResourceMap::const_iterator it = copy.begin(); it != end; ++it) {
1105         RefPtr<ResourceLoader> loader = it->first;
1106         WebResource *resource = it->second.get();
1107         NSData *data = [[resource data] retain];
1108         loader->didReceiveResponse([resource _response]);
1109         loader->didReceiveData(data, [data length], true);
1110         [data release];
1111         loader->didFinishLoading();
1112     }
1113 }
1114
1115 bool WebFrameLoaderClient::createPageCache(WebHistoryItem *item)
1116 {
1117     WebCorePageState *pageState = [[WebCorePageState alloc] initWithPage:core(m_webFrame.get())->page()];
1118     if (!pageState) {
1119         [item setHasPageCache:NO];
1120         return false;
1121     }
1122
1123     [item setHasPageCache:YES];
1124     NSMutableDictionary *pageCache = [item pageCache];
1125
1126     [pageCache setObject:pageState forKey:WebCorePageCacheStateKey];
1127     [pageCache setObject:[NSDate date] forKey:WebPageCacheEntryDateKey];
1128     [pageCache setObject:[m_webFrame.get() dataSource] forKey:WebPageCacheDataSourceKey];
1129     [pageCache setObject:[m_webFrame->_private->webFrameView documentView] forKey:WebPageCacheDocumentViewKey];
1130
1131     [pageState release];
1132
1133     return true;
1134 }
1135
1136 RetainPtr<WebFramePolicyListener> WebFrameLoaderClient::setUpPolicyListener(FramePolicyFunction function)
1137 {
1138     ASSERT(!m_policyListener);
1139     ASSERT(!m_policyFunction);
1140
1141     [m_policyListener.get() invalidate];
1142
1143     WebFramePolicyListener *listener = [[WebFramePolicyListener alloc] initWithWebCoreFrame:core(m_webFrame.get())];
1144     m_policyListener = listener;
1145     [listener release];
1146     m_policyFunction = function;
1147
1148     return listener;
1149 }
1150
1151 void WebFrameLoaderClient::receivedPolicyDecison(PolicyAction action)
1152 {
1153     ASSERT(m_policyListener);
1154     ASSERT(m_policyFunction);
1155
1156     FramePolicyFunction function = m_policyFunction;
1157
1158     m_policyListener = nil;
1159     m_policyFunction = 0;
1160
1161     (core(m_webFrame.get())->loader()->*function)(action);
1162 }
1163
1164 String WebFrameLoaderClient::userAgent()
1165 {
1166     return [getWebView(m_webFrame.get()) _userAgent];
1167 }
1168
1169 NSDictionary *WebFrameLoaderClient::actionDictionary(const NavigationAction& action) const
1170 {
1171     unsigned modifierFlags = 0;
1172     const Event* event = action.event();
1173     if (event && (event->isMouseEvent() || event->isKeyboardEvent())) {
1174         if (static_cast<const UIEventWithKeyState*>(event)->ctrlKey())
1175             modifierFlags |= NSControlKeyMask;
1176         if (static_cast<const UIEventWithKeyState*>(event)->altKey())
1177             modifierFlags |= NSAlternateKeyMask;
1178         if (static_cast<const UIEventWithKeyState*>(event)->shiftKey())
1179             modifierFlags |= NSShiftKeyMask;
1180         if (static_cast<const UIEventWithKeyState*>(event)->metaKey())
1181             modifierFlags |= NSCommandKeyMask;
1182     }
1183     if (event && event->isMouseEvent()) {
1184         IntPoint point(static_cast<const MouseEvent*>(event)->clientX(),
1185             static_cast<const MouseEvent*>(event)->clientY());
1186         WebElementDictionary *element = [[WebElementDictionary alloc]
1187             initWithHitTestResult:core(m_webFrame.get())->hitTestResultAtPoint(point, false)];
1188         NSDictionary *result = [NSDictionary dictionaryWithObjectsAndKeys:
1189             [NSNumber numberWithInt:action.type()], WebActionNavigationTypeKey,
1190             element, WebActionElementKey,
1191             [NSNumber numberWithInt:static_cast<const MouseEvent*>(event)->button()], WebActionButtonKey,
1192             [NSNumber numberWithInt:modifierFlags], WebActionModifierFlagsKey,
1193             action.URL().getNSURL(), WebActionOriginalURLKey,
1194             nil];
1195         [element release];
1196         return result;
1197     }
1198     return [NSDictionary dictionaryWithObjectsAndKeys:
1199         [NSNumber numberWithInt:action.type()], WebActionNavigationTypeKey,
1200         [NSNumber numberWithInt:modifierFlags], WebActionModifierFlagsKey,
1201         action.URL().getNSURL(), WebActionOriginalURLKey,
1202         nil];
1203 }
1204
1205 @implementation WebFramePolicyListener
1206
1207 - (id)initWithWebCoreFrame:(Frame*)frame
1208 {
1209     self = [self init];
1210     if (!self)
1211         return nil;
1212     frame->ref();
1213     m_frame = frame;
1214     return self;
1215 }
1216
1217 - (void)invalidate
1218 {
1219     if (m_frame) {
1220         m_frame->deref();
1221         m_frame = 0;
1222     }
1223 }
1224
1225 - (void)dealloc
1226 {
1227     if (m_frame)
1228         m_frame->deref();
1229     [super dealloc];
1230 }
1231
1232 - (void)finalize
1233 {
1234     if (m_frame)
1235         m_frame->deref();
1236     [super finalize];
1237 }
1238
1239 - (void)receivedPolicyDecision:(PolicyAction)action
1240 {
1241     RefPtr<Frame> frame = adoptRef(m_frame);
1242     m_frame = 0;
1243     if (frame)
1244         static_cast<WebFrameLoaderClient*>(frame->loader()->client())->receivedPolicyDecison(action);
1245 }
1246
1247 - (void)ignore
1248 {
1249     [self receivedPolicyDecision:PolicyIgnore];
1250 }
1251
1252 - (void)download
1253 {
1254     [self receivedPolicyDecision:PolicyDownload];
1255 }
1256
1257 - (void)use
1258 {
1259     [self receivedPolicyDecision:PolicyUse];
1260 }
1261
1262 - (void)continue
1263 {
1264     [self receivedPolicyDecision:PolicyUse];
1265 }
1266
1267 @end