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