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