18b4e1c1d52f84e1ceecd6edfa8fb2cbd730edcb
[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 "WebPolicyDelegatePrivate.h"
40 #import "WebDefaultResourceLoadDelegate.h"
41 #import "WebDocumentInternal.h"
42 #import "WebDocumentLoaderMac.h"
43 #import "WebDownloadInternal.h"
44 #import "WebElementDictionary.h"
45 #import "WebFormDelegate.h"
46 #import "WebFrameBridge.h"
47 #import "WebFrameInternal.h"
48 #import "WebFrameLoadDelegate.h"
49 #import "WebFrameViewInternal.h"
50 #import "WebHTMLRepresentation.h"
51 #import "WebHTMLView.h"
52 #import "WebHistoryItemInternal.h"
53 #import "WebHistoryItemPrivate.h"
54 #import "WebHistoryPrivate.h"
55 #import "WebIconDatabaseInternal.h"
56 #import "WebKitErrorsPrivate.h"
57 #import "WebKitNSStringExtras.h"
58 #import "WebNSURLExtras.h"
59 #import "WebPanelAuthenticationHandler.h"
60 #import "WebPolicyDelegate.h"
61 #import "WebPreferences.h"
62 #import "WebResourceLoadDelegate.h"
63 #import "WebResourcePrivate.h"
64 #import "WebScriptDebugServerPrivate.h"
65 #import "WebUIDelegate.h"
66 #import "WebViewInternal.h"
67 #import <WebCore/AuthenticationMac.h>
68 #import <WebCore/Chrome.h>
69 #import <WebCore/Document.h>
70 #import <WebCore/DocumentLoader.h>
71 #import <WebCore/EventHandler.h>
72 #import <WebCore/FormState.h>
73 #import <WebCore/FrameLoader.h>
74 #import <WebCore/FrameLoaderTypes.h>
75 #import <WebCore/FrameMac.h>
76 #import <WebCore/FrameTree.h>
77 #import <WebCore/HistoryItem.h>
78 #import <WebCore/HitTestResult.h>
79 #import <WebCore/HTMLFormElement.h>
80 #import <WebCore/IconDatabase.h>
81 #import <WebCore/MouseEvent.h>
82 #import <WebCore/Page.h>
83 #import <WebCore/PageCache.h>
84 #import <WebCore/PageState.h>
85 #import <WebCore/PlatformString.h>
86 #import <WebCore/ResourceError.h>
87 #import <WebCore/ResourceHandle.h>
88 #import <WebCore/ResourceLoader.h>
89 #import <WebCore/ResourceRequest.h>
90 #import <WebCore/WebCoreFrameBridge.h>
91 #import <WebCore/WebDataProtocol.h>
92 #import <WebKit/DOMHTMLFormElement.h>
93 #import <WebKitSystemInterface.h>
94 #import <wtf/PassRefPtr.h>
95
96 using namespace WebCore;
97
98 @interface WebFramePolicyListener : NSObject <WebPolicyDecisionListener, WebFormSubmissionListener>
99 {
100     Frame* m_frame;
101 }
102 - (id)initWithWebCoreFrame:(Frame*)frame;
103 - (void)invalidate;
104 @end
105
106 static inline WebView *getWebView(DocumentLoader* loader)
107 {
108     return kit(loader->frameLoader()->frame()->page());
109 }
110
111 static inline WebDataSource *dataSource(DocumentLoader* loader)
112 {
113     return loader ? static_cast<WebDocumentLoaderMac*>(loader)->dataSource() : nil;
114 }
115
116 WebFrameLoaderClient::WebFrameLoaderClient(WebFrame *webFrame)
117     : m_webFrame(webFrame)
118     , m_policyFunction(0)
119     , m_archivedResourcesDeliveryTimer(this, &WebFrameLoaderClient::deliverArchivedResources)
120 {
121 }
122
123 void WebFrameLoaderClient::frameLoaderDestroyed()
124 {
125     delete this;
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::privateBrowsingEnabled() const
139 {
140     return [[getWebView(m_webFrame.get()) preferences] privateBrowsingEnabled];
141 }
142
143 void WebFrameLoaderClient::makeDocumentView()
144 {
145     WebFrameView *v = m_webFrame->_private->webFrameView;
146     WebDataSource *ds = [m_webFrame.get() dataSource];
147
148     NSView <WebDocumentView> *documentView = [v _makeDocumentViewForDataSource:ds];
149     if (!documentView)
150         return;
151
152     WebFrameBridge *bridge = m_webFrame->_private->bridge;
153
154     // FIXME: We could save work and not do this for a top-level view that is not a WebHTMLView.
155     [bridge createFrameViewWithNSView:documentView marginWidth:[v _marginWidth] marginHeight:[v _marginHeight]];
156     [m_webFrame.get() _updateBackground];
157     [bridge installInFrame:[v _scrollView]];
158
159     // Call setDataSource on the document view after it has been placed in the view hierarchy.
160     // This what we for the top-level view, so should do this for views in subframes as well.
161     [documentView setDataSource:ds];
162 }
163
164 void WebFrameLoaderClient::makeRepresentation(DocumentLoader* loader)
165 {
166     [dataSource(loader) _makeRepresentation];
167 }
168
169 void WebFrameLoaderClient::setDocumentViewFromPageCache(PageCache* pageCache)
170 {
171     DocumentLoader* cachedDocumentLoader = pageCache->documentLoader();
172     ASSERT(cachedDocumentLoader);
173     NSView <WebDocumentView> *cachedView = pageCache->documentView();
174     ASSERT(cachedView != nil);
175     [cachedView setDataSource:dataSource(cachedDocumentLoader)];
176     [m_webFrame->_private->webFrameView _setDocumentView:cachedView];
177 }
178
179 void WebFrameLoaderClient::forceLayout()
180 {
181     NSView <WebDocumentView> *view = [m_webFrame->_private->webFrameView documentView];
182     if ([view isKindOfClass:[WebHTMLView class]])
183         [(WebHTMLView *)view setNeedsToApplyStyles:YES];
184     [view setNeedsLayout:YES];
185     [view layout];
186 }
187
188 void WebFrameLoaderClient::forceLayoutForNonHTML()
189 {
190     WebFrameView *thisView = m_webFrame->_private->webFrameView;
191     NSView <WebDocumentView> *thisDocumentView = [thisView documentView];
192     ASSERT(thisDocumentView != nil);
193     
194     // Tell the just loaded document to layout.  This may be necessary
195     // for non-html content that needs a layout message.
196     if (!([[m_webFrame.get() dataSource] _isDocumentHTML])) {
197         [thisDocumentView setNeedsLayout:YES];
198         [thisDocumentView layout];
199         [thisDocumentView setNeedsDisplay:YES];
200     }
201 }
202
203 void WebFrameLoaderClient::setCopiesOnScroll()
204 {
205     [[[m_webFrame->_private->webFrameView _scrollView] contentView] setCopiesOnScroll:YES];
206 }
207
208 void WebFrameLoaderClient::detachedFromParent1()
209 {
210     Frame* coreFrame = core(m_webFrame.get());
211     if (coreFrame)
212         coreFrame->loader()->saveScrollPositionAndViewStateToItem(coreFrame->loader()->currentHistoryItem());
213 }
214
215 void WebFrameLoaderClient::detachedFromParent2()
216 {
217     [m_webFrame->_private->inspectors makeObjectsPerformSelector:@selector(_webFrameDetached:) withObject:m_webFrame.get()];
218     [m_webFrame->_private->webFrameView _setWebFrame:nil]; // needed for now to be compatible w/ old behavior
219 }
220
221 void WebFrameLoaderClient::detachedFromParent3()
222 {
223     [m_webFrame->_private->webFrameView release];
224     m_webFrame->_private->webFrameView = nil;
225 }
226
227 void WebFrameLoaderClient::detachedFromParent4()
228 {
229     m_webFrame->_private->bridge = nil;
230 }
231
232 void WebFrameLoaderClient::loadedFromPageCache()
233 {
234     // Release the resources kept in the page cache.
235     // They will be reset when we leave this page.
236     // The WebCore side of the page cache will have already been invalidated by
237     // the bridge to prevent premature release.
238     core(m_webFrame.get())->loader()->currentHistoryItem()->setHasPageCache(false);
239 }
240
241 void WebFrameLoaderClient::download(ResourceHandle* handle, const ResourceRequest& request, const ResourceResponse& response)
242 {
243     id proxy = handle->releaseProxy();
244     ASSERT(proxy);
245     [WebDownload _downloadWithLoadingConnection:handle->connection()
246                                         request:request.nsURLRequest()
247                                        response:response.nsURLResponse()
248                                        delegate:[getWebView(m_webFrame.get()) downloadDelegate]
249                                           proxy:proxy];
250 }
251
252 bool WebFrameLoaderClient::dispatchDidLoadResourceFromMemoryCache(DocumentLoader* loader, const ResourceRequest& request, const ResourceResponse& response, int length)
253 {
254     WebView *webView = getWebView(loader);
255     id resourceLoadDelegate = WebViewGetResourceLoadDelegate(webView);
256     WebResourceDelegateImplementationCache implementations = WebViewGetResourceLoadDelegateImplementations(webView);
257
258     if (!implementations.delegateImplementsDidLoadResourceFromMemoryCache)
259         return false;
260
261     implementations.didLoadResourceFromMemoryCacheFunc(resourceLoadDelegate, @selector(webView:didLoadResourceFromMemoryCache:response:length:fromDataSource:), webView, request.nsURLRequest(), response.nsURLResponse(), length, dataSource(loader));
262     return true;
263 }
264
265 void WebFrameLoaderClient::assignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader* loader, const ResourceRequest& request)
266 {
267     WebView *webView = getWebView(loader);
268     id resourceLoadDelegate = WebViewGetResourceLoadDelegate(webView);
269     WebResourceDelegateImplementationCache implementations = WebViewGetResourceLoadDelegateImplementations(webView);
270
271     id object;
272     BOOL shouldRelease = NO;
273     if (implementations.delegateImplementsIdentifierForRequest)
274         object = implementations.identifierForRequestFunc(resourceLoadDelegate, @selector(webView:identifierForInitialRequest:fromDataSource:), webView, request.nsURLRequest(), dataSource(loader));
275     else {
276         object = [[NSObject alloc] init];
277         shouldRelease = YES;
278     }
279     [webView _addObject:object forIdentifier:identifier];
280     if (shouldRelease)
281         [object release];
282 }
283
284 void WebFrameLoaderClient::dispatchWillSendRequest(DocumentLoader* loader, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse)
285 {
286     WebView *webView = getWebView(loader);
287     id resourceLoadDelegate = WebViewGetResourceLoadDelegate(webView);
288     WebResourceDelegateImplementationCache implementations = WebViewGetResourceLoadDelegateImplementations(webView);
289
290     if (implementations.delegateImplementsWillSendRequest)
291         request = implementations.willSendRequestFunc(resourceLoadDelegate, @selector(webView:resource:willSendRequest:redirectResponse:fromDataSource:), webView, [webView _objectForIdentifier:identifier], request.nsURLRequest(), redirectResponse.nsURLResponse(), dataSource(loader));
292 }
293
294 void WebFrameLoaderClient::dispatchDidReceiveAuthenticationChallenge(DocumentLoader* loader, unsigned long identifier, const AuthenticationChallenge& challenge)
295 {
296     WebView *webView = getWebView(m_webFrame.get());
297     id resourceLoadDelegate = [webView resourceLoadDelegate];
298     WebResourceDelegateImplementationCache implementations = WebViewGetResourceLoadDelegateImplementations(webView);
299
300     NSURLAuthenticationChallenge *webChallenge = mac(challenge);
301
302     if (implementations.delegateImplementsDidReceiveAuthenticationChallenge) {
303         [resourceLoadDelegate webView:webView resource:[webView _objectForIdentifier:identifier] didReceiveAuthenticationChallenge:webChallenge fromDataSource:dataSource(loader)];
304         return;
305     }
306
307     NSWindow *window = [webView hostWindow] ? [webView hostWindow] : [webView window];
308     [[WebPanelAuthenticationHandler sharedHandler] startAuthentication:webChallenge window:window];
309 }
310
311 void WebFrameLoaderClient::dispatchDidCancelAuthenticationChallenge(DocumentLoader* loader, unsigned long identifier, const AuthenticationChallenge&challenge)
312 {
313     WebView *webView = getWebView(m_webFrame.get());
314     id resourceLoadDelegate = [webView resourceLoadDelegate];
315     WebResourceDelegateImplementationCache implementations = WebViewGetResourceLoadDelegateImplementations(webView);
316
317     NSURLAuthenticationChallenge *webChallenge = mac(challenge);
318
319     if (implementations.delegateImplementsDidCancelAuthenticationChallenge) {
320         [resourceLoadDelegate webView:webView resource:[webView _objectForIdentifier:identifier] didCancelAuthenticationChallenge:webChallenge fromDataSource:dataSource(loader)];
321         return;
322     }
323
324     [(WebPanelAuthenticationHandler *)[WebPanelAuthenticationHandler sharedHandler] cancelAuthentication:webChallenge];
325 }
326
327 void WebFrameLoaderClient::dispatchDidReceiveResponse(DocumentLoader* loader, unsigned long identifier, const ResourceResponse& response)
328 {
329     WebView *webView = getWebView(loader);
330     id resourceLoadDelegate = WebViewGetResourceLoadDelegate(webView);
331     WebResourceDelegateImplementationCache implementations = WebViewGetResourceLoadDelegateImplementations(webView);
332
333     if (implementations.delegateImplementsDidReceiveResponse)
334         implementations.didReceiveResponseFunc(resourceLoadDelegate, @selector(webView:resource:didReceiveResponse:fromDataSource:), webView, [webView _objectForIdentifier:identifier], response.nsURLResponse(), dataSource(loader));
335 }
336
337 void WebFrameLoaderClient::dispatchDidReceiveContentLength(DocumentLoader* loader, unsigned long identifier, int lengthReceived)
338 {
339     WebView *webView = getWebView(loader);
340     id resourceLoadDelegate = WebViewGetResourceLoadDelegate(webView);
341     WebResourceDelegateImplementationCache implementations = WebViewGetResourceLoadDelegateImplementations(webView);
342
343     if (implementations.delegateImplementsDidReceiveContentLength)
344         implementations.didReceiveContentLengthFunc(resourceLoadDelegate, @selector(webView:resource:didReceiveContentLength:fromDataSource:), webView, [webView _objectForIdentifier:identifier], (WebNSUInteger)lengthReceived, dataSource(loader));
345 }
346
347 void WebFrameLoaderClient::dispatchDidFinishLoading(DocumentLoader* loader, unsigned long identifier)
348 {
349     WebView *webView = getWebView(loader);
350     id resourceLoadDelegate = WebViewGetResourceLoadDelegate(webView);
351     WebResourceDelegateImplementationCache implementations = WebViewGetResourceLoadDelegateImplementations(webView);
352     
353     if (implementations.delegateImplementsDidFinishLoadingFromDataSource)
354         implementations.didFinishLoadingFromDataSourceFunc(resourceLoadDelegate, @selector(webView:resource:didFinishLoadingFromDataSource:), webView, [webView _objectForIdentifier:identifier], dataSource(loader));
355     [webView _removeObjectForIdentifier:identifier];
356 }
357
358 void WebFrameLoaderClient::dispatchDidFailLoading(DocumentLoader* loader, unsigned long identifier, const WebCore::ResourceError& error)
359 {
360     WebView *webView = getWebView(m_webFrame.get());
361     [[webView _resourceLoadDelegateForwarder] webView:webView resource:[webView _objectForIdentifier:identifier] didFailLoadingWithError:error fromDataSource:dataSource(loader)];
362     [webView _removeObjectForIdentifier:identifier];
363 }
364
365 void WebFrameLoaderClient::dispatchDidHandleOnloadEvents()
366 {
367     WebView *webView = getWebView(m_webFrame.get());
368     [[webView _frameLoadDelegateForwarder] webView:webView didHandleOnloadEventsForFrame:m_webFrame.get()];
369 }
370
371 void WebFrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad()
372 {
373     WebView *webView = getWebView(m_webFrame.get());
374     [[webView _frameLoadDelegateForwarder] webView:webView
375        didReceiveServerRedirectForProvisionalLoadForFrame:m_webFrame.get()];
376 }
377
378 void WebFrameLoaderClient::dispatchDidCancelClientRedirect()
379 {
380     WebView *webView = getWebView(m_webFrame.get());
381     [[webView _frameLoadDelegateForwarder] webView:webView didCancelClientRedirectForFrame:m_webFrame.get()];
382 }
383
384 void WebFrameLoaderClient::dispatchWillPerformClientRedirect(const KURL& URL, double delay, double fireDate)
385 {
386     WebView *webView = getWebView(m_webFrame.get());
387     [[webView _frameLoadDelegateForwarder] webView:webView
388                          willPerformClientRedirectToURL:URL.getNSURL()
389                                                   delay:delay
390                                                fireDate:[NSDate dateWithTimeIntervalSince1970:fireDate]
391                                                forFrame:m_webFrame.get()];
392 }
393
394 void WebFrameLoaderClient::dispatchDidChangeLocationWithinPage()
395 {
396     WebView *webView = getWebView(m_webFrame.get());   
397     [[webView _frameLoadDelegateForwarder] webView:webView didChangeLocationWithinPageForFrame:m_webFrame.get()];
398 }
399
400 void WebFrameLoaderClient::dispatchWillClose()
401 {
402     WebView *webView = getWebView(m_webFrame.get());   
403     [[webView _frameLoadDelegateForwarder] webView:webView willCloseFrame:m_webFrame.get()];
404 }
405
406 void WebFrameLoaderClient::dispatchDidReceiveIcon()
407 {
408     WebView *webView = getWebView(m_webFrame.get());   
409     ASSERT([m_webFrame.get() _isMainFrame]);
410     // FIXME: This willChangeValueForKey call is too late, because the icon has already changed by now.
411     [webView _willChangeValueForKey:_WebMainFrameIconKey];
412     id delegate = [webView frameLoadDelegate];
413     if ([delegate respondsToSelector:@selector(webView:didReceiveIcon:forFrame:)]) {
414         Image* image = IconDatabase::sharedIconDatabase()->
415             iconForPageURL(core(m_webFrame.get())->loader()->url().url(), IntSize(16, 16));
416         NSImage *icon = webGetNSImage(image, NSMakeSize(16, 16));
417         if (icon)
418             [delegate webView:webView didReceiveIcon:icon forFrame:m_webFrame.get()];
419     }
420     [webView _didChangeValueForKey:_WebMainFrameIconKey];
421 }
422
423 void WebFrameLoaderClient::dispatchDidStartProvisionalLoad()
424 {
425     WebView *webView = getWebView(m_webFrame.get());   
426     [webView _didStartProvisionalLoadForFrame:m_webFrame.get()];
427     [[webView _frameLoadDelegateForwarder] webView:webView didStartProvisionalLoadForFrame:m_webFrame.get()];    
428 }
429
430 void WebFrameLoaderClient::dispatchDidReceiveTitle(const String& title)
431 {
432     WebView *webView = getWebView(m_webFrame.get());   
433     [[webView _frameLoadDelegateForwarder] webView:webView didReceiveTitle:title forFrame:m_webFrame.get()];
434 }
435
436 void WebFrameLoaderClient::dispatchDidCommitLoad()
437 {
438     // Tell the client we've committed this URL.
439     ASSERT([m_webFrame->_private->webFrameView documentView] != nil);
440     
441     WebView *webView = getWebView(m_webFrame.get());   
442     [webView _didCommitLoadForFrame:m_webFrame.get()];
443     [[webView _frameLoadDelegateForwarder] webView:webView didCommitLoadForFrame:m_webFrame.get()];
444 }
445
446 void WebFrameLoaderClient::dispatchDidFailProvisionalLoad(const ResourceError& error)
447 {
448     WebView *webView = getWebView(m_webFrame.get());   
449     [webView _didFailProvisionalLoadWithError:error forFrame:m_webFrame.get()];
450     [[webView _frameLoadDelegateForwarder] webView:webView didFailProvisionalLoadWithError:error forFrame:m_webFrame.get()];
451     [m_webFrame->_private->internalLoadDelegate webFrame:m_webFrame.get() didFinishLoadWithError:error];
452 }
453
454 void WebFrameLoaderClient::dispatchDidFailLoad(const ResourceError& error)
455 {
456     WebView *webView = getWebView(m_webFrame.get());   
457     [webView _didFailLoadWithError:error forFrame:m_webFrame.get()];
458     [[webView _frameLoadDelegateForwarder] webView:webView didFailLoadWithError:error forFrame:m_webFrame.get()];
459     [m_webFrame->_private->internalLoadDelegate webFrame:m_webFrame.get() didFinishLoadWithError:error];
460 }
461
462 void WebFrameLoaderClient::dispatchDidFinishDocumentLoad()
463 {
464     WebView *webView = getWebView(m_webFrame.get());
465     id delegate = [webView frameLoadDelegate];
466     if ([delegate respondsToSelector:@selector(webView:didFinishDocumentLoadForFrame:)])
467         [delegate webView:webView didFinishDocumentLoadForFrame:m_webFrame.get()];
468 }
469
470 void WebFrameLoaderClient::dispatchDidFinishLoad()
471 {
472     WebView *webView = getWebView(m_webFrame.get());   
473     [webView _didFinishLoadForFrame:m_webFrame.get()];
474     [[webView _frameLoadDelegateForwarder] webView:webView didFinishLoadForFrame:m_webFrame.get()];
475     [m_webFrame->_private->internalLoadDelegate webFrame:m_webFrame.get() didFinishLoadWithError:nil];
476 }
477
478 void WebFrameLoaderClient::dispatchDidFirstLayout()
479 {
480     WebView *webView = getWebView(m_webFrame.get());
481     [[webView _frameLoadDelegateForwarder] webView:webView didFirstLayoutInFrame:m_webFrame.get()];
482 }
483
484 Frame* WebFrameLoaderClient::dispatchCreatePage()
485 {
486     WebView *currentWebView = getWebView(m_webFrame.get());
487     id wd = [currentWebView UIDelegate];
488     if ([wd respondsToSelector:@selector(webView:createWebViewWithRequest:)])
489         return core([[wd webView:currentWebView createWebViewWithRequest:nil] mainFrame]);
490     return 0;
491 }
492
493 void WebFrameLoaderClient::dispatchShow()
494 {
495     WebView *webView = getWebView(m_webFrame.get());
496     [[webView _UIDelegateForwarder] webViewShow:webView];
497 }
498
499 void WebFrameLoaderClient::dispatchDecidePolicyForMIMEType(FramePolicyFunction function,
500     const String& MIMEType, const ResourceRequest& request)
501 {
502     WebView *webView = getWebView(m_webFrame.get());
503
504     [[webView _policyDelegateForwarder] webView:webView
505                         decidePolicyForMIMEType:MIMEType
506                                         request:request.nsURLRequest()
507                                           frame:m_webFrame.get()
508                                decisionListener:setUpPolicyListener(function).get()];
509 }
510
511 void WebFrameLoaderClient::dispatchDecidePolicyForNewWindowAction(FramePolicyFunction function,
512     const NavigationAction& action, const ResourceRequest& request, const String& frameName)
513 {
514     WebView *webView = getWebView(m_webFrame.get());
515     [[webView _policyDelegateForwarder] webView:webView
516             decidePolicyForNewWindowAction:actionDictionary(action)
517                                    request:request.nsURLRequest()
518                               newFrameName:frameName
519                           decisionListener:setUpPolicyListener(function).get()];
520 }
521
522 void WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction(FramePolicyFunction function,
523     const NavigationAction& action, const ResourceRequest& request)
524 {
525     WebView *webView = getWebView(m_webFrame.get());
526     [[webView _policyDelegateForwarder] webView:webView
527                 decidePolicyForNavigationAction:actionDictionary(action)
528                                         request:request.nsURLRequest()
529                                           frame:m_webFrame.get()
530                                decisionListener:setUpPolicyListener(function).get()];
531 }
532
533 void WebFrameLoaderClient::cancelPolicyCheck()
534 {
535     [m_policyListener.get() invalidate];
536     m_policyListener = nil;
537     m_policyFunction = 0;
538 }
539
540 void WebFrameLoaderClient::dispatchUnableToImplementPolicy(const ResourceError& error)
541 {
542     WebView *webView = getWebView(m_webFrame.get());
543     [[webView _policyDelegateForwarder] webView:webView
544         unableToImplementPolicyWithError:error frame:m_webFrame.get()];    
545 }
546
547 void WebFrameLoaderClient::dispatchWillSubmitForm(FramePolicyFunction function, PassRefPtr<FormState> formState)
548 {
549     id <WebFormDelegate> formDelegate = [getWebView(m_webFrame.get()) _formDelegate];
550     if (!formDelegate) {
551         (core(m_webFrame.get())->loader()->*function)(PolicyUse);
552         return;
553     }
554
555     NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] initWithCapacity:formState->values().size()];
556     HashMap<String, String>::const_iterator end = formState->values().end();
557     for (HashMap<String, String>::const_iterator it = formState->values().begin(); it != end; ++it)
558         if (!it->first.isNull() && !it->second.isNull())
559             [dictionary setObject:it->second forKey:it->first];
560
561     [formDelegate frame:m_webFrame.get()
562             sourceFrame:kit(formState->sourceFrame())
563          willSubmitForm:kit(formState->form())
564              withValues:dictionary
565      submissionListener:setUpPolicyListener(function).get()];
566
567     [dictionary release];
568 }
569
570 void WebFrameLoaderClient::dispatchDidLoadMainResource(DocumentLoader* loader)
571 {
572     if ([WebScriptDebugServer listenerCount])
573         [[WebScriptDebugServer sharedScriptDebugServer] webView:getWebView(m_webFrame.get())
574             didLoadMainResourceForDataSource:dataSource(loader)];
575 }
576
577 void WebFrameLoaderClient::revertToProvisionalState(DocumentLoader* loader)
578 {
579     [dataSource(loader) _revertToProvisionalState];
580 }
581
582 void WebFrameLoaderClient::setMainDocumentError(DocumentLoader* loader, const ResourceError& error)
583 {
584     [dataSource(loader) _setMainDocumentError:error];
585 }
586
587 void WebFrameLoaderClient::clearUnarchivingState(DocumentLoader* loader)
588 {
589     [dataSource(loader) _clearUnarchivingState];
590 }
591
592 void WebFrameLoaderClient::willChangeEstimatedProgress()
593 {
594     [getWebView(m_webFrame.get()) _willChangeValueForKey:_WebEstimatedProgressKey];
595 }
596
597 void WebFrameLoaderClient::didChangeEstimatedProgress()
598 {
599     [getWebView(m_webFrame.get()) _didChangeValueForKey:_WebEstimatedProgressKey];
600 }
601
602 void WebFrameLoaderClient::postProgressStartedNotification()
603 {
604     [[NSNotificationCenter defaultCenter] postNotificationName:WebViewProgressStartedNotification object:getWebView(m_webFrame.get())];
605 }
606
607 void WebFrameLoaderClient::postProgressEstimateChangedNotification()
608 {
609     [[NSNotificationCenter defaultCenter] postNotificationName:WebViewProgressEstimateChangedNotification object:getWebView(m_webFrame.get())];
610 }
611
612 void WebFrameLoaderClient::postProgressFinishedNotification()
613 {
614     [[NSNotificationCenter defaultCenter] postNotificationName:WebViewProgressFinishedNotification object:getWebView(m_webFrame.get())];
615 }
616
617 void WebFrameLoaderClient::setMainFrameDocumentReady(bool ready)
618 {
619     [getWebView(m_webFrame.get()) setMainFrameDocumentReady:ready];
620 }
621
622 void WebFrameLoaderClient::startDownload(const ResourceRequest& request)
623 {
624     // FIXME: Should download full request.
625     [getWebView(m_webFrame.get()) _downloadURL:request.url().getNSURL()];
626 }
627
628 void WebFrameLoaderClient::willChangeTitle(DocumentLoader* loader)
629 {
630     // FIXME: Should do this only in main frame case, right?
631     [getWebView(m_webFrame.get()) _willChangeValueForKey:_WebMainFrameTitleKey];
632 }
633
634 void WebFrameLoaderClient::didChangeTitle(DocumentLoader* loader)
635 {
636     // FIXME: Should do this only in main frame case, right?
637     [getWebView(m_webFrame.get()) _didChangeValueForKey:_WebMainFrameTitleKey];
638 }
639
640 void WebFrameLoaderClient::committedLoad(DocumentLoader* loader, const char* data, int length)
641 {
642     NSData *nsData = [[NSData alloc] initWithBytesNoCopy:(void*)data length:length freeWhenDone:NO];
643     [dataSource(loader) _receivedData:nsData];
644     [nsData release];
645 }
646
647 void WebFrameLoaderClient::finishedLoading(DocumentLoader* loader)
648 {
649     [dataSource(loader) _finishedLoading];
650 }
651
652 void WebFrameLoaderClient::finalSetupForReplace(DocumentLoader* loader)
653 {
654     [dataSource(loader) _clearUnarchivingState];
655 }
656
657 // FIXME: <rdar://problem/4880065> - Push Global History into WebCore
658 // Once that task is complete, this will go away
659 void WebFrameLoaderClient::updateGlobalHistoryForStandardLoad(const KURL& url)
660 {
661     NSURL *nsurl = url.getNSURL();
662     WebHistoryItem *entry = [[WebHistory optionalSharedHistory] addItemForURL:nsurl];
663     String pageTitle = core(m_webFrame.get())->loader()->documentLoader()->title();
664     if (pageTitle.length())
665         [entry setTitle:pageTitle];
666 }
667  
668 // FIXME: <rdar://problem/4880065> - Push Global History into WebCore
669 // Once that task is complete, this will go away
670 void WebFrameLoaderClient::updateGlobalHistoryForReload(const KURL& url)
671 {
672     WebHistory *sharedHistory = [WebHistory optionalSharedHistory];
673     WebHistoryItem *item = [sharedHistory itemForURL:url.getNSURL()];
674     if (item)
675         [sharedHistory setLastVisitedTimeInterval:[NSDate timeIntervalSinceReferenceDate] forItem:item];
676 }
677
678 bool WebFrameLoaderClient::shouldGoToHistoryItem(HistoryItem* item) const
679 {
680     WebView* view = getWebView(m_webFrame.get());
681     WebHistoryItem *webItem = kit(item);
682     
683     return [[view _policyDelegateForwarder] webView:view shouldGoToHistoryItem:webItem];
684 }
685
686 ResourceError WebFrameLoaderClient::cancelledError(const ResourceRequest &request)
687 {
688     return [NSError _webKitErrorWithDomain:NSURLErrorDomain code:NSURLErrorCancelled URL:request.url().getNSURL()];
689 }
690
691 ResourceError WebFrameLoaderClient::cannotShowURLError(const ResourceRequest& request)
692 {
693     return [NSError _webKitErrorWithDomain:WebKitErrorDomain code:WebKitErrorCannotShowURL URL:request.url().getNSURL()];
694 }
695
696 ResourceError WebFrameLoaderClient::interruptForPolicyChangeError(const ResourceRequest& request)
697 {
698     return [NSError _webKitErrorWithDomain:WebKitErrorDomain code:WebKitErrorFrameLoadInterruptedByPolicyChange URL:request.url().getNSURL()];
699 }
700
701 ResourceError WebFrameLoaderClient::cannotShowMIMETypeError(const ResourceResponse& response)
702 {
703     return [NSError _webKitErrorWithDomain:NSURLErrorDomain code:WebKitErrorCannotShowMIMEType URL:response.url().getNSURL()];
704 }
705
706 ResourceError WebFrameLoaderClient::fileDoesNotExistError(const ResourceResponse& response)
707 {
708     return [NSError _webKitErrorWithDomain:NSURLErrorDomain code:NSURLErrorFileDoesNotExist URL:response.url().getNSURL()];    
709 }
710
711 bool WebFrameLoaderClient::shouldFallBack(const ResourceError& error)
712 {
713     // FIXME: Needs to check domain.
714     // FIXME: WebKitErrorPlugInWillHandleLoad is a workaround for the cancel we do to prevent
715     // loading plugin content twice.  See <rdar://problem/4258008>
716     return error.errorCode() != NSURLErrorCancelled && error.errorCode() != WebKitErrorPlugInWillHandleLoad;
717 }
718
719 void WebFrameLoaderClient::setDefersLoading(bool defers)
720 {
721     if (!defers)
722         deliverArchivedResourcesAfterDelay();
723 }
724
725 bool WebFrameLoaderClient::willUseArchive(ResourceLoader* loader, const ResourceRequest& request, const KURL& originalURL) const
726 {
727     if (request.url() != originalURL)
728         return false;
729     if (!canUseArchivedResource(request.nsURLRequest()))
730         return false;
731     WebResource *resource = [dataSource(core(m_webFrame.get())->loader()->activeDocumentLoader()) _archivedSubresourceForURL:originalURL.getNSURL()];
732     if (!resource)
733         return false;
734     if (!canUseArchivedResource([resource _response]))
735         return false;
736     m_pendingArchivedResources.set(loader, resource);
737     // Deliver the resource after a delay because callers don't expect to receive callbacks while calling this method.
738     deliverArchivedResourcesAfterDelay();
739     return true;
740 }
741
742 bool WebFrameLoaderClient::isArchiveLoadPending(ResourceLoader* loader) const
743 {
744     return m_pendingArchivedResources.contains(loader);
745 }
746
747 void WebFrameLoaderClient::cancelPendingArchiveLoad(ResourceLoader* loader)
748 {
749     if (m_pendingArchivedResources.isEmpty())
750         return;
751     m_pendingArchivedResources.remove(loader);
752     if (m_pendingArchivedResources.isEmpty())
753         m_archivedResourcesDeliveryTimer.stop();
754 }
755
756 void WebFrameLoaderClient::clearArchivedResources()
757 {
758     m_pendingArchivedResources.clear();
759     m_archivedResourcesDeliveryTimer.stop();
760 }
761
762 bool WebFrameLoaderClient::canHandleRequest(const ResourceRequest& request) const
763 {
764     return [WebView _canHandleRequest:request.nsURLRequest()];
765 }
766
767 bool WebFrameLoaderClient::canShowMIMEType(const String& MIMEType) const
768 {
769     return [WebView canShowMIMEType:MIMEType];
770 }
771
772 bool WebFrameLoaderClient::representationExistsForURLScheme(const String& URLScheme) const
773 {
774     return [WebView _representationExistsForURLScheme:URLScheme];
775 }
776
777 String WebFrameLoaderClient::generatedMIMETypeForURLScheme(const String& URLScheme) const
778 {
779     return [WebView _generatedMIMETypeForURLScheme:URLScheme];
780 }
781
782 void WebFrameLoaderClient::frameLoadCompleted()
783 {
784     // Note: Can be called multiple times.
785     // Even if already complete, we might have set a previous item on a frame that
786     // didn't do any data loading on the past transaction. Make sure to clear these out.
787     NSScrollView *sv = [m_webFrame->_private->webFrameView _scrollView];
788     if ([getWebView(m_webFrame.get()) drawsBackground])
789         [sv setDrawsBackground:YES];
790     core(m_webFrame.get())->loader()->setPreviousHistoryItem(0);
791 }
792
793
794 void WebFrameLoaderClient::saveScrollPositionAndViewStateToItem(HistoryItem* item)
795 {
796     if (!item)
797         return;
798     
799     NSView <WebDocumentView> *docView = [m_webFrame->_private->webFrameView documentView];
800     NSView *parent = [docView superview];
801
802     // we might already be detached when this is called from detachFromParent, in which
803     // case we don't want to override real data earlier gathered with (0,0)
804     if (parent) {
805         NSPoint point;
806         if ([docView conformsToProtocol:@protocol(_WebDocumentViewState)]) {
807             // The view has it's own idea of where it is scrolled to, perhaps because it contains its own
808             // ScrollView instead of using the one provided by the WebFrame
809             point = [(id <_WebDocumentViewState>)docView scrollPoint];
810             item->setViewState([(id <_WebDocumentViewState>)docView viewState]);
811         } else {
812             // Parent is the clipview of the DynamicScrollView the WebFrame installs
813             ASSERT([parent isKindOfClass:[NSClipView class]]);
814             point = [parent bounds].origin;
815         }
816         item->setScrollPoint(IntPoint(point));
817     }
818 }
819
820 /*
821  There is a race condition between the layout and load completion that affects restoring the scroll position.
822  We try to restore the scroll position at both the first layout and upon load completion.
823  
824  1) If first layout happens before the load completes, we want to restore the scroll position then so that the
825  first time we draw the page is already scrolled to the right place, instead of starting at the top and later
826  jumping down.  It is possible that the old scroll position is past the part of the doc laid out so far, in
827  which case the restore silent fails and we will fix it in when we try to restore on doc completion.
828  2) If the layout happens after the load completes, the attempt to restore at load completion time silently
829  fails.  We then successfully restore it when the layout happens.
830 */
831 void WebFrameLoaderClient::restoreScrollPositionAndViewState()
832 {
833     HistoryItem* currentItem = core(m_webFrame.get())->loader()->currentHistoryItem();
834     ASSERT(currentItem);
835
836     // FIXME: As the ASSERT attests, it seems we should always have a currentItem here.
837     // One counterexample is <rdar://problem/4917290>
838     // For now, to cover this issue in release builds, there is no technical harm to returning
839     // early and from a user standpoint - as in the above radar - the previous page load failed 
840     // so there *is* no scroll state to restore!
841     if (!currentItem)
842         return;
843     
844     NSView <WebDocumentView> *docView = [m_webFrame->_private->webFrameView documentView];
845     NSPoint point = currentItem->scrollPoint();
846     if ([docView conformsToProtocol:@protocol(_WebDocumentViewState)]) {        
847         id state = currentItem->viewState();
848         if (state) {
849             [(id <_WebDocumentViewState>)docView setViewState:state];
850         }
851         
852         [(id <_WebDocumentViewState>)docView setScrollPoint:point];
853     } else {
854         [docView scrollPoint:point];
855     }
856 }
857
858 void WebFrameLoaderClient::provisionalLoadStarted()
859 {    
860     // FIXME: This is OK as long as no one resizes the window,
861     // but in the case where someone does, it means garbage outside
862     // the occupied part of the scroll view.
863     [[m_webFrame->_private->webFrameView _scrollView] setDrawsBackground:NO];
864 }
865
866 void WebFrameLoaderClient::didFinishLoad()
867 {
868     [m_webFrame->_private->internalLoadDelegate webFrame:m_webFrame.get() didFinishLoadWithError:nil];    
869 }
870
871 void WebFrameLoaderClient::prepareForDataSourceReplacement()
872 {
873     if (![m_webFrame.get() dataSource]) {
874         ASSERT(!core(m_webFrame.get())->tree()->childCount());
875         return;
876     }
877     
878     // Make sure that any work that is triggered by resigning first reponder can get done.
879     // The main example where this came up is the textDidEndEditing that is sent to the
880     // FormsDelegate (3223413).  We need to do this before _detachChildren, since that will
881     // remove the views as a side-effect of freeing the bridge, at which point we can't
882     // post the FormDelegate messages.
883     //
884     // Note that this can also take FirstResponder away from a child of our frameView that
885     // is not in a child frame's view.  This is OK because we are in the process
886     // of loading new content, which will blow away all editors in this top frame, and if
887     // a non-editor is firstReponder it will not be affected by endEditingFor:.
888     // Potentially one day someone could write a DocView whose editors were not all
889     // replaced by loading new content, but that does not apply currently.
890     NSView *frameView = m_webFrame->_private->webFrameView;
891     NSWindow *window = [frameView window];
892     NSResponder *firstResp = [window firstResponder];
893     if ([firstResp isKindOfClass:[NSView class]] && [(NSView *)firstResp isDescendantOf:frameView])
894         [window endEditingFor:firstResp];
895     
896     core(m_webFrame.get())->loader()->detachChildren();
897 }
898
899 PassRefPtr<DocumentLoader> WebFrameLoaderClient::createDocumentLoader(const ResourceRequest& request)
900 {
901     RefPtr<WebDocumentLoaderMac> loader = new WebDocumentLoaderMac(request);
902
903     WebDataSource *dataSource = [[WebDataSource alloc] _initWithDocumentLoader:loader.get()];
904     loader->setDataSource(dataSource);
905     [dataSource release];
906
907     return loader.release();
908 }
909
910 // FIXME: <rdar://problem/4880065> - Push Global History into WebCore
911 // Once that task is complete, this will go away
912 void WebFrameLoaderClient::setTitle(const String& title, const KURL& URL)
913 {
914     NSString *titleNSString = title;
915     [[[WebHistory optionalSharedHistory] itemForURL:URL.getNSURL()] setTitle:titleNSString];
916     if (HistoryItem* item = core(m_webFrame.get())->loader()->currentHistoryItem())
917         item->setTitle(title);
918 }
919
920 // The following 2 functions are copied from [NSHTTPURLProtocol _cachedResponsePassesValidityChecks] and modified for our needs.
921 // FIXME: It would be nice to eventually to share this logic somehow.
922 bool WebFrameLoaderClient::canUseArchivedResource(NSURLRequest *request) const
923 {
924     NSURLRequestCachePolicy policy = [request cachePolicy];
925     if (policy == NSURLRequestReturnCacheDataElseLoad)
926         return true;
927     if (policy == NSURLRequestReturnCacheDataDontLoad)
928         return true;
929     if (policy == NSURLRequestReloadIgnoringCacheData)
930         return false;
931     if ([request valueForHTTPHeaderField:@"must-revalidate"] != nil)
932         return false;
933     if ([request valueForHTTPHeaderField:@"proxy-revalidate"] != nil)
934         return false;
935     if ([request valueForHTTPHeaderField:@"If-Modified-Since"] != nil)
936         return false;
937     if ([request valueForHTTPHeaderField:@"Cache-Control"] != nil)
938         return false;
939     if ([@"POST" _webkit_isCaseInsensitiveEqualToString:[request HTTPMethod]])
940         return false;
941     return true;
942 }
943
944 bool WebFrameLoaderClient::canUseArchivedResource(NSURLResponse *response) const
945 {
946     if (WKGetNSURLResponseMustRevalidate(response))
947         return false;
948     if (WKGetNSURLResponseCalculatedExpiration(response) - CFAbsoluteTimeGetCurrent() < 1)
949         return false;
950     return true;
951 }
952
953 void WebFrameLoaderClient::deliverArchivedResourcesAfterDelay() const
954 {
955     if (m_pendingArchivedResources.isEmpty())
956         return;
957     if (core(m_webFrame.get())->page()->defersLoading())
958         return;
959     if (!m_archivedResourcesDeliveryTimer.isActive())
960         m_archivedResourcesDeliveryTimer.startOneShot(0);
961 }
962
963 void WebFrameLoaderClient::deliverArchivedResources(Timer<WebFrameLoaderClient>*)
964 {
965     if (m_pendingArchivedResources.isEmpty())
966         return;
967     if (core(m_webFrame.get())->page()->defersLoading())
968         return;
969
970     const ResourceMap copy = m_pendingArchivedResources;
971     m_pendingArchivedResources.clear();
972
973     ResourceMap::const_iterator end = copy.end();
974     for (ResourceMap::const_iterator it = copy.begin(); it != end; ++it) {
975         RefPtr<ResourceLoader> loader = it->first;
976         WebResource *resource = it->second.get();
977         NSData *data = [[resource data] retain];
978         loader->didReceiveResponse([resource _response]);
979         loader->didReceiveData((const char*)[data bytes], [data length], [data length], true);
980         [data release];
981         loader->didFinishLoading();
982     }
983 }
984
985 void WebFrameLoaderClient::saveDocumentViewToPageCache(PageCache* pageCache)
986 {
987     pageCache->setDocumentView([m_webFrame->_private->webFrameView documentView]);
988 }
989
990 RetainPtr<WebFramePolicyListener> WebFrameLoaderClient::setUpPolicyListener(FramePolicyFunction function)
991 {
992     ASSERT(!m_policyListener);
993     ASSERT(!m_policyFunction);
994
995     [m_policyListener.get() invalidate];
996
997     WebFramePolicyListener *listener = [[WebFramePolicyListener alloc] initWithWebCoreFrame:core(m_webFrame.get())];
998     m_policyListener = listener;
999     [listener release];
1000     m_policyFunction = function;
1001
1002     return listener;
1003 }
1004
1005 void WebFrameLoaderClient::receivedPolicyDecison(PolicyAction action)
1006 {
1007     ASSERT(m_policyListener);
1008     ASSERT(m_policyFunction);
1009
1010     FramePolicyFunction function = m_policyFunction;
1011
1012     m_policyListener = nil;
1013     m_policyFunction = 0;
1014
1015     (core(m_webFrame.get())->loader()->*function)(action);
1016 }
1017
1018 String WebFrameLoaderClient::userAgent()
1019 {
1020     return [getWebView(m_webFrame.get()) _userAgent];
1021 }
1022
1023 static const MouseEvent* findMouseEvent(const Event* event)
1024 {
1025     for (const Event* e = event; e; e = e->underlyingEvent())
1026         if (e->isMouseEvent())
1027             return static_cast<const MouseEvent*>(e);
1028     return 0;
1029 }
1030
1031 NSDictionary *WebFrameLoaderClient::actionDictionary(const NavigationAction& action) const
1032 {
1033     unsigned modifierFlags = 0;
1034     const Event* event = action.event();
1035     if (const UIEventWithKeyState* keyStateEvent = findEventWithKeyState(const_cast<Event*>(event))) {
1036         if (keyStateEvent->ctrlKey())
1037             modifierFlags |= NSControlKeyMask;
1038         if (keyStateEvent->altKey())
1039             modifierFlags |= NSAlternateKeyMask;
1040         if (keyStateEvent->shiftKey())
1041             modifierFlags |= NSShiftKeyMask;
1042         if (keyStateEvent->metaKey())
1043             modifierFlags |= NSCommandKeyMask;
1044     }
1045     if (const MouseEvent* mouseEvent = findMouseEvent(event)) {
1046         IntPoint point(mouseEvent->clientX(), mouseEvent->clientY());
1047         WebElementDictionary *element = [[WebElementDictionary alloc]
1048             initWithHitTestResult:core(m_webFrame.get())->eventHandler()->hitTestResultAtPoint(point, false)];
1049         NSDictionary *result = [NSDictionary dictionaryWithObjectsAndKeys:
1050             [NSNumber numberWithInt:action.type()], WebActionNavigationTypeKey,
1051             element, WebActionElementKey,
1052             [NSNumber numberWithInt:mouseEvent->button()], WebActionButtonKey,
1053             [NSNumber numberWithInt:modifierFlags], WebActionModifierFlagsKey,
1054             action.URL().getNSURL(), WebActionOriginalURLKey,
1055             nil];
1056         [element release];
1057         return result;
1058     }
1059     return [NSDictionary dictionaryWithObjectsAndKeys:
1060         [NSNumber numberWithInt:action.type()], WebActionNavigationTypeKey,
1061         [NSNumber numberWithInt:modifierFlags], WebActionModifierFlagsKey,
1062         action.URL().getNSURL(), WebActionOriginalURLKey,
1063         nil];
1064 }
1065
1066 bool WebFrameLoaderClient::canCachePage() const
1067 {
1068     // We can only cache HTML pages right now
1069     return [[[m_webFrame.get() dataSource] representation] isKindOfClass:[WebHTMLRepresentation class]];
1070 }
1071
1072 @implementation WebFramePolicyListener
1073
1074 - (id)initWithWebCoreFrame:(Frame*)frame
1075 {
1076     self = [self init];
1077     if (!self)
1078         return nil;
1079     frame->ref();
1080     m_frame = frame;
1081     return self;
1082 }
1083
1084 - (void)invalidate
1085 {
1086     if (m_frame) {
1087         m_frame->deref();
1088         m_frame = 0;
1089     }
1090 }
1091
1092 - (void)dealloc
1093 {
1094     if (m_frame)
1095         m_frame->deref();
1096     [super dealloc];
1097 }
1098
1099 - (void)finalize
1100 {
1101     if (m_frame)
1102         m_frame->deref();
1103     [super finalize];
1104 }
1105
1106 - (void)receivedPolicyDecision:(PolicyAction)action
1107 {
1108     RefPtr<Frame> frame = adoptRef(m_frame);
1109     m_frame = 0;
1110     if (frame)
1111         static_cast<WebFrameLoaderClient*>(frame->loader()->client())->receivedPolicyDecison(action);
1112 }
1113
1114 - (void)ignore
1115 {
1116     [self receivedPolicyDecision:PolicyIgnore];
1117 }
1118
1119 - (void)download
1120 {
1121     [self receivedPolicyDecision:PolicyDownload];
1122 }
1123
1124 - (void)use
1125 {
1126     [self receivedPolicyDecision:PolicyUse];
1127 }
1128
1129 - (void)continue
1130 {
1131     [self receivedPolicyDecision:PolicyUse];
1132 }
1133
1134
1135
1136 @end