2008-11-04 Anders Carlsson <andersca@apple.com>
[webkit/qt.git] / WebKit / mac / WebCoreSupport / WebFrameLoaderClient.mm
blobe6aa35f101459508a3aedcdfeece331845d235d3
1 /*
2  * Copyright (C) 2006, 2007, 2008 Apple 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  */
29 #import "WebFrameLoaderClient.h"
31 // Terrible hack; lets us get at the WebFrame private structure.
32 #define private public
33 #import "WebFrame.h"
34 #undef private
36 #import "DOMElementInternal.h"
37 #import "WebBackForwardList.h"
38 #import "WebCachedPagePlatformData.h"
39 #import "WebChromeClient.h"
40 #import "WebDataSourceInternal.h"
41 #import "WebDocumentInternal.h"
42 #import "WebDocumentLoaderMac.h"
43 #import "WebDownloadInternal.h"
44 #import "WebDynamicScrollBarsViewInternal.h"
45 #import "WebElementDictionary.h"
46 #import "WebFormDelegate.h"
47 #import "WebFrameInternal.h"
48 #import "WebFrameLoadDelegate.h"
49 #import "WebFrameViewInternal.h"
50 #import "WebHTMLRepresentationPrivate.h"
51 #import "WebHTMLViewInternal.h"
52 #import "WebHistoryItemInternal.h"
53 #import "WebHistoryInternal.h"
54 #import "WebIconDatabaseInternal.h"
55 #import "WebKitErrorsPrivate.h"
56 #import "WebKitLogging.h"
57 #import "WebKitNSStringExtras.h"
58 #import "WebNSURLExtras.h"
59 #import "WebBaseNetscapePluginView.h"
60 #import "WebNetscapePluginPackage.h"
61 #import "WebNullPluginView.h"
62 #import "WebPanelAuthenticationHandler.h"
63 #import "WebPluginController.h"
64 #import "WebPluginPackage.h"
65 #import "WebPluginViewFactoryPrivate.h"
66 #import "WebPolicyDelegate.h"
67 #import "WebPolicyDelegatePrivate.h"
68 #import "WebPreferences.h"
69 #import "WebResourceLoadDelegate.h"
70 #import "WebResourcePrivate.h"
71 #import "WebUIDelegate.h"
72 #import "WebUIDelegatePrivate.h"
73 #import "WebViewInternal.h"
74 #import <WebKitSystemInterface.h>
75 #import <WebCore/AuthenticationMac.h>
76 #import <WebCore/BlockExceptions.h>
77 #import <WebCore/CachedPage.h>
78 #import <WebCore/Chrome.h>
79 #import <WebCore/Document.h>
80 #import <WebCore/DocumentLoader.h>
81 #import <WebCore/EventHandler.h>
82 #import <WebCore/FormState.h>
83 #import <WebCore/Frame.h>
84 #import <WebCore/FrameLoader.h>
85 #import <WebCore/FrameLoaderTypes.h>
86 #import <WebCore/FrameTree.h>
87 #import <WebCore/FrameView.h>
88 #import <WebCore/HTMLFormElement.h>
89 #import <WebCore/HTMLFrameElement.h>
90 #import <WebCore/HTMLFrameOwnerElement.h>
91 #import <WebCore/HTMLNames.h>
92 #import <WebCore/HistoryItem.h>
93 #import <WebCore/HitTestResult.h>
94 #import <WebCore/IconDatabase.h>
95 #import <WebCore/LoaderNSURLExtras.h>
96 #import <WebCore/MIMETypeRegistry.h>
97 #import <WebCore/MouseEvent.h>
98 #import <WebCore/Page.h>
99 #import <WebCore/PlatformString.h>
100 #import <WebCore/ResourceError.h>
101 #import <WebCore/ResourceHandle.h>
102 #import <WebCore/ResourceLoader.h>
103 #import <WebCore/ResourceRequest.h>
104 #import <WebCore/ScriptController.h>
105 #import <WebCore/SharedBuffer.h>
106 #import <WebCore/WebCoreObjCExtras.h>
107 #import <WebCore/Widget.h>
108 #import <WebKit/DOMElement.h>
109 #import <WebKit/DOMHTMLFormElement.h>
110 #import <wtf/PassRefPtr.h>
112 #if ENABLE(MAC_JAVA_BRIDGE)
113 #import "WebJavaPlugIn.h"
114 #endif
116 using namespace WebCore;
117 using namespace HTMLNames;
119 #if ENABLE(MAC_JAVA_BRIDGE)
120 @interface NSView (WebJavaPluginDetails)
121 - (jobject)pollForAppletInWindow:(NSWindow *)window;
122 @end
123 #endif
125 @interface NSURLDownload (WebNSURLDownloadDetails)
126 - (void)_setOriginatingURL:(NSURL *)originatingURL;
127 @end
129 // For backwards compatibility with older WebKit plug-ins.
130 NSString *WebPluginBaseURLKey = @"WebPluginBaseURL";
131 NSString *WebPluginAttributesKey = @"WebPluginAttributes";
132 NSString *WebPluginContainerKey = @"WebPluginContainer";
134 @interface WebFramePolicyListener : NSObject <WebPolicyDecisionListener, WebFormSubmissionListener> {
135     Frame* m_frame;
137 - (id)initWithWebCoreFrame:(Frame*)frame;
138 - (void)invalidate;
139 @end
141 static inline WebDataSource *dataSource(DocumentLoader* loader)
143     return loader ? static_cast<WebDocumentLoaderMac*>(loader)->dataSource() : nil;
146 WebFrameLoaderClient::WebFrameLoaderClient(WebFrame *webFrame)
147     : m_webFrame(webFrame)
148     , m_policyFunction(0)
152 void WebFrameLoaderClient::frameLoaderDestroyed()
154     [m_webFrame.get() _clearCoreFrame];
155     delete this;
158 bool WebFrameLoaderClient::hasWebView() const
160     return [m_webFrame.get() webView] != nil;
163 void WebFrameLoaderClient::makeRepresentation(DocumentLoader* loader)
165     [dataSource(loader) _makeRepresentation];
168 bool WebFrameLoaderClient::hasHTMLView() const
170     NSView <WebDocumentView> *view = [m_webFrame->_private->webFrameView documentView];
171     return [view isKindOfClass:[WebHTMLView class]];
174 void WebFrameLoaderClient::forceLayout()
176     NSView <WebDocumentView> *view = [m_webFrame->_private->webFrameView documentView];
177     if ([view isKindOfClass:[WebHTMLView class]])
178         [(WebHTMLView *)view setNeedsToApplyStyles:YES];
179     [view setNeedsLayout:YES];
180     [view layout];
183 void WebFrameLoaderClient::forceLayoutForNonHTML()
185     WebFrameView *thisView = m_webFrame->_private->webFrameView;
186     if (!thisView) // Viewless mode.
187         return;
188     NSView <WebDocumentView> *thisDocumentView = [thisView documentView];
189     ASSERT(thisDocumentView != nil);
190     
191     // Tell the just loaded document to layout.  This may be necessary
192     // for non-html content that needs a layout message.
193     if (!([[m_webFrame.get() _dataSource] _isDocumentHTML])) {
194         [thisDocumentView setNeedsLayout:YES];
195         [thisDocumentView layout];
196         [thisDocumentView setNeedsDisplay:YES];
197     }
200 void WebFrameLoaderClient::setCopiesOnScroll()
202     [[[m_webFrame->_private->webFrameView _scrollView] contentView] setCopiesOnScroll:YES];
205 void WebFrameLoaderClient::detachedFromParent2()
207     //remove any NetScape plugins that are children of this frame because they are about to be detached
208     WebView *webView = getWebView(m_webFrame.get());
209     [webView removePluginInstanceViewsFor:(m_webFrame.get())];
210     [m_webFrame->_private->webFrameView _setWebFrame:nil]; // needed for now to be compatible w/ old behavior
213 void WebFrameLoaderClient::detachedFromParent3()
215     [m_webFrame->_private->webFrameView release];
216     m_webFrame->_private->webFrameView = nil;
219 void WebFrameLoaderClient::download(ResourceHandle* handle, const ResourceRequest& request, const ResourceRequest& initialRequest, const ResourceResponse& response)
221     id proxy = handle->releaseProxy();
222     ASSERT(proxy);
223     
224     WebView *webView = getWebView(m_webFrame.get());
225     WebDownload *download = [WebDownload _downloadWithLoadingConnection:handle->connection()
226                                                                 request:request.nsURLRequest()
227                                                                response:response.nsURLResponse()
228                                                                delegate:[webView downloadDelegate]
229                                                                   proxy:proxy];
230     
231     setOriginalURLForDownload(download, initialRequest);    
234 void WebFrameLoaderClient::setOriginalURLForDownload(WebDownload *download, const ResourceRequest& initialRequest) const
236     NSURLRequest *initialURLRequest = initialRequest.nsURLRequest();
237     NSURL *originalURL = nil;
238     
239     // If there was no referrer, don't traverse the back/forward history
240     // since this download was initiated directly. <rdar://problem/5294691>
241     if ([initialURLRequest valueForHTTPHeaderField:@"Referer"]) {
242         // find the first item in the history that was originated by the user
243         WebView *webView = getWebView(m_webFrame.get());
244         WebBackForwardList *history = [webView backForwardList];
245         int backListCount = [history backListCount];
246         for (int backIndex = 0; backIndex <= backListCount && !originalURL; backIndex++) {
247             // FIXME: At one point we had code here to check a "was user gesture" flag.
248             // Do we need to restore that logic?
249             originalURL = [[history itemAtIndex:-backIndex] URL];
250         }
251     }
253     if (!originalURL)
254         originalURL = [initialURLRequest URL];
256     if ([download respondsToSelector:@selector(_setOriginatingURL:)]) {
257         NSString *scheme = [originalURL scheme];
258         NSString *host = [originalURL host];
259         if (scheme && host && [scheme length] && [host length]) {
260             NSNumber *port = [originalURL port];
261             if (port && [port intValue] < 0)
262                 port = nil;
263             NSString *hostOnlyURLString;
264             if (port)
265                 hostOnlyURLString = [[NSString alloc] initWithFormat:@"%@://%@:%d", scheme, host, [port intValue]];
266             else
267                 hostOnlyURLString = [[NSString alloc] initWithFormat:@"%@://%@", scheme, host];
268             NSURL *hostOnlyURL = [[NSURL alloc] initWithString:hostOnlyURLString];
269             [hostOnlyURLString release];
270             [download _setOriginatingURL:hostOnlyURL];
271             [hostOnlyURL release];
272         }
273     }
276 bool WebFrameLoaderClient::dispatchDidLoadResourceFromMemoryCache(DocumentLoader* loader, const ResourceRequest& request, const ResourceResponse& response, int length)
278     WebView *webView = getWebView(m_webFrame.get());
279     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
280     if (!implementations->didLoadResourceFromMemoryCacheFunc)
281         return false;
283     CallResourceLoadDelegate(implementations->didLoadResourceFromMemoryCacheFunc, webView, @selector(webView:didLoadResourceFromMemoryCache:response:length:fromDataSource:), request.nsURLRequest(), response.nsURLResponse(), length, dataSource(loader));
284     return true;
287 void WebFrameLoaderClient::assignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader* loader, const ResourceRequest& request)
289     WebView *webView = getWebView(m_webFrame.get());
290     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
292     id object = nil;
293     BOOL shouldRelease = NO;
294     if (implementations->identifierForRequestFunc)
295         object = CallResourceLoadDelegate(implementations->identifierForRequestFunc, webView, @selector(webView:identifierForInitialRequest:fromDataSource:), request.nsURLRequest(), dataSource(loader));
296     else {
297         object = [[NSObject alloc] init];
298         shouldRelease = YES;
299     }
301     [webView _addObject:object forIdentifier:identifier];
303     if (shouldRelease)
304         [object release];
307 void WebFrameLoaderClient::dispatchWillSendRequest(DocumentLoader* loader, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse)
309     WebView *webView = getWebView(m_webFrame.get());
310     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
312     if (redirectResponse.isNull())
313         static_cast<WebDocumentLoaderMac*>(loader)->increaseLoadCount(identifier);
315     if (implementations->willSendRequestFunc)
316         request = (NSURLRequest *)CallResourceLoadDelegate(implementations->willSendRequestFunc, webView, @selector(webView:resource:willSendRequest:redirectResponse:fromDataSource:), [webView _objectForIdentifier:identifier], request.nsURLRequest(), redirectResponse.nsURLResponse(), dataSource(loader));
319 void WebFrameLoaderClient::dispatchDidReceiveAuthenticationChallenge(DocumentLoader* loader, unsigned long identifier, const AuthenticationChallenge& challenge)
321     WebView *webView = getWebView(m_webFrame.get());
322     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
324     NSURLAuthenticationChallenge *webChallenge = mac(challenge);
326     if (implementations->didReceiveAuthenticationChallengeFunc) {
327         if (id resource = [webView _objectForIdentifier:identifier]) {
328             CallResourceLoadDelegate(implementations->didReceiveAuthenticationChallengeFunc, webView, @selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:), resource, webChallenge, dataSource(loader));
329             return;
330         }
331     }
333     NSWindow *window = [webView hostWindow] ? [webView hostWindow] : [webView window];
334     [[WebPanelAuthenticationHandler sharedHandler] startAuthentication:webChallenge window:window];
337 void WebFrameLoaderClient::dispatchDidCancelAuthenticationChallenge(DocumentLoader* loader, unsigned long identifier, const AuthenticationChallenge&challenge)
339     WebView *webView = getWebView(m_webFrame.get());
340     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
341     NSURLAuthenticationChallenge *webChallenge = mac(challenge);
343     if (implementations->didCancelAuthenticationChallengeFunc) {
344         if (id resource = [webView _objectForIdentifier:identifier]) {
345             CallResourceLoadDelegate(implementations->didCancelAuthenticationChallengeFunc, webView, @selector(webView:resource:didCancelAuthenticationChallenge:fromDataSource:), resource, webChallenge, dataSource(loader));
346             return;
347         }
348     }
350     [(WebPanelAuthenticationHandler *)[WebPanelAuthenticationHandler sharedHandler] cancelAuthentication:webChallenge];
353 void WebFrameLoaderClient::dispatchDidReceiveResponse(DocumentLoader* loader, unsigned long identifier, const ResourceResponse& response)
355     WebView *webView = getWebView(m_webFrame.get());
356     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
357     if (implementations->didReceiveResponseFunc) {
358         if (id resource = [webView _objectForIdentifier:identifier])
359             CallResourceLoadDelegate(implementations->didReceiveResponseFunc, webView, @selector(webView:resource:didReceiveResponse:fromDataSource:), resource, response.nsURLResponse(), dataSource(loader));
360     }
363 NSCachedURLResponse* WebFrameLoaderClient::willCacheResponse(DocumentLoader* loader, unsigned long identifier, NSCachedURLResponse* response) const
365     WebView *webView = getWebView(m_webFrame.get());
366     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
368     if (implementations->willCacheResponseFunc) {
369         if (id resource = [webView _objectForIdentifier:identifier])
370             return CallResourceLoadDelegate(implementations->willCacheResponseFunc, webView, @selector(webView:resource:willCacheResponse:fromDataSource:), resource, response, dataSource(loader));
371     }
373     return response;
376 void WebFrameLoaderClient::dispatchDidReceiveContentLength(DocumentLoader* loader, unsigned long identifier, int lengthReceived)
378     WebView *webView = getWebView(m_webFrame.get());
379     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
380     if (implementations->didReceiveContentLengthFunc) {
381         if (id resource = [webView _objectForIdentifier:identifier])
382             CallResourceLoadDelegate(implementations->didReceiveContentLengthFunc, webView, @selector(webView:resource:didReceiveContentLength:fromDataSource:), resource, (NSInteger)lengthReceived, dataSource(loader));
383     }
386 void WebFrameLoaderClient::dispatchDidFinishLoading(DocumentLoader* loader, unsigned long identifier)
388     WebView *webView = getWebView(m_webFrame.get());
389     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
391     if (implementations->didFinishLoadingFromDataSourceFunc) {
392         if (id resource = [webView _objectForIdentifier:identifier])
393             CallResourceLoadDelegate(implementations->didFinishLoadingFromDataSourceFunc, webView, @selector(webView:resource:didFinishLoadingFromDataSource:), resource, dataSource(loader));
394     }
396     [webView _removeObjectForIdentifier:identifier];
398     static_cast<WebDocumentLoaderMac*>(loader)->decreaseLoadCount(identifier);
401 void WebFrameLoaderClient::dispatchDidFailLoading(DocumentLoader* loader, unsigned long identifier, const ResourceError& error)
403     WebView *webView = getWebView(m_webFrame.get());
404     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
406     if (implementations->didFailLoadingWithErrorFromDataSourceFunc) {
407         if (id resource = [webView _objectForIdentifier:identifier])
408             CallResourceLoadDelegate(implementations->didFailLoadingWithErrorFromDataSourceFunc, webView, @selector(webView:resource:didFailLoadingWithError:fromDataSource:), resource, (NSError *)error, dataSource(loader));
409     }
411     [webView _removeObjectForIdentifier:identifier];
413     static_cast<WebDocumentLoaderMac*>(loader)->decreaseLoadCount(identifier);
416 void WebFrameLoaderClient::dispatchDidHandleOnloadEvents()
418     WebView *webView = getWebView(m_webFrame.get());
419     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
420     if (implementations->didHandleOnloadEventsForFrameFunc)
421         CallFrameLoadDelegate(implementations->didHandleOnloadEventsForFrameFunc, webView, @selector(webView:didHandleOnloadEventsForFrame:), m_webFrame.get());
424 void WebFrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad()
426     WebView *webView = getWebView(m_webFrame.get());
427     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
428     if (implementations->didReceiveServerRedirectForProvisionalLoadForFrameFunc)
429         CallFrameLoadDelegate(implementations->didReceiveServerRedirectForProvisionalLoadForFrameFunc, webView, @selector(webView:didReceiveServerRedirectForProvisionalLoadForFrame:), m_webFrame.get());
432 void WebFrameLoaderClient::dispatchDidCancelClientRedirect()
434     WebView *webView = getWebView(m_webFrame.get());
435     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
436     if (implementations->didCancelClientRedirectForFrameFunc)
437         CallFrameLoadDelegate(implementations->didCancelClientRedirectForFrameFunc, webView, @selector(webView:didCancelClientRedirectForFrame:), m_webFrame.get());
440 void WebFrameLoaderClient::dispatchWillPerformClientRedirect(const KURL& url, double delay, double fireDate)
442     WebView *webView = getWebView(m_webFrame.get());
443     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
444     if (implementations->willPerformClientRedirectToURLDelayFireDateForFrameFunc) {
445         NSURL *cocoaURL = url;
446         CallFrameLoadDelegate(implementations->willPerformClientRedirectToURLDelayFireDateForFrameFunc, webView, @selector(webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:), cocoaURL, delay, [NSDate dateWithTimeIntervalSince1970:fireDate], m_webFrame.get());
447     }
450 void WebFrameLoaderClient::dispatchDidChangeLocationWithinPage()
452     WebView *webView = getWebView(m_webFrame.get());
453     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
454     if (implementations->didChangeLocationWithinPageForFrameFunc)
455         CallFrameLoadDelegate(implementations->didChangeLocationWithinPageForFrameFunc, webView, @selector(webView:didChangeLocationWithinPageForFrame:), m_webFrame.get());
458 void WebFrameLoaderClient::dispatchWillClose()
460     WebView *webView = getWebView(m_webFrame.get());   
461     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
462     if (implementations->willCloseFrameFunc)
463         CallFrameLoadDelegate(implementations->willCloseFrameFunc, webView, @selector(webView:willCloseFrame:), m_webFrame.get());
466 void WebFrameLoaderClient::dispatchDidReceiveIcon()
468     WebView *webView = getWebView(m_webFrame.get());   
469     ASSERT(m_webFrame == [webView mainFrame]);
470     [webView _dispatchDidReceiveIconFromWebFrame:m_webFrame.get()];
473 void WebFrameLoaderClient::dispatchDidStartProvisionalLoad()
475     WebView *webView = getWebView(m_webFrame.get());   
476     [webView _didStartProvisionalLoadForFrame:m_webFrame.get()];
478     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
479     if (implementations->didStartProvisionalLoadForFrameFunc)
480         CallFrameLoadDelegate(implementations->didStartProvisionalLoadForFrameFunc, webView, @selector(webView:didStartProvisionalLoadForFrame:), m_webFrame.get());
483 void WebFrameLoaderClient::dispatchDidReceiveTitle(const String& title)
485     WebView *webView = getWebView(m_webFrame.get());   
486     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
487     if (implementations->didReceiveTitleForFrameFunc)
488         CallFrameLoadDelegate(implementations->didReceiveTitleForFrameFunc, webView, @selector(webView:didReceiveTitle:forFrame:), (NSString *)title, m_webFrame.get());
491 void WebFrameLoaderClient::dispatchDidCommitLoad()
493     // Tell the client we've committed this URL.
494     ASSERT([m_webFrame->_private->webFrameView documentView] != nil || ![getWebView(m_webFrame.get()) _usesDocumentViews]);
495     
496     WebView *webView = getWebView(m_webFrame.get());   
497     [webView _didCommitLoadForFrame:m_webFrame.get()];
499     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
500     if (implementations->didCommitLoadForFrameFunc)
501         CallFrameLoadDelegate(implementations->didCommitLoadForFrameFunc, webView, @selector(webView:didCommitLoadForFrame:), m_webFrame.get());
504 void WebFrameLoaderClient::dispatchDidFailProvisionalLoad(const ResourceError& error)
506     WebView *webView = getWebView(m_webFrame.get());   
507     [webView _didFailProvisionalLoadWithError:error forFrame:m_webFrame.get()];
509     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
510     if (implementations->didFailProvisionalLoadWithErrorForFrameFunc)
511         CallFrameLoadDelegate(implementations->didFailProvisionalLoadWithErrorForFrameFunc, webView, @selector(webView:didFailProvisionalLoadWithError:forFrame:), (NSError *)error, m_webFrame.get());
513     [m_webFrame->_private->internalLoadDelegate webFrame:m_webFrame.get() didFinishLoadWithError:error];
516 void WebFrameLoaderClient::dispatchDidFailLoad(const ResourceError& error)
518     WebView *webView = getWebView(m_webFrame.get());   
519     [webView _didFailLoadWithError:error forFrame:m_webFrame.get()];
521     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
522     if (implementations->didFailLoadWithErrorForFrameFunc)
523         CallFrameLoadDelegate(implementations->didFailLoadWithErrorForFrameFunc, webView, @selector(webView:didFailLoadWithError:forFrame:), (NSError *)error, m_webFrame.get());
525     [m_webFrame->_private->internalLoadDelegate webFrame:m_webFrame.get() didFinishLoadWithError:error];
528 void WebFrameLoaderClient::dispatchDidFinishDocumentLoad()
530     WebView *webView = getWebView(m_webFrame.get());
531     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
532     if (implementations->didFinishDocumentLoadForFrameFunc)
533         CallFrameLoadDelegate(implementations->didFinishDocumentLoadForFrameFunc, webView, @selector(webView:didFinishDocumentLoadForFrame:), m_webFrame.get());
536 void WebFrameLoaderClient::dispatchDidFinishLoad()
538     WebView *webView = getWebView(m_webFrame.get());   
539     [webView _didFinishLoadForFrame:m_webFrame.get()];
541     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
542     if (implementations->didFinishLoadForFrameFunc)
543         CallFrameLoadDelegate(implementations->didFinishLoadForFrameFunc, webView, @selector(webView:didFinishLoadForFrame:), m_webFrame.get());
545     [m_webFrame->_private->internalLoadDelegate webFrame:m_webFrame.get() didFinishLoadWithError:nil];
548 void WebFrameLoaderClient::dispatchDidFirstLayout()
550     WebView *webView = getWebView(m_webFrame.get());
551     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
552     if (implementations->didFirstLayoutInFrameFunc)
553         CallFrameLoadDelegate(implementations->didFirstLayoutInFrameFunc, webView, @selector(webView:didFirstLayoutInFrame:), m_webFrame.get());
556 Frame* WebFrameLoaderClient::dispatchCreatePage()
558     WebView *currentWebView = getWebView(m_webFrame.get());
559     NSDictionary *features = [[NSDictionary alloc] init];
560     WebView *newWebView = [[currentWebView _UIDelegateForwarder] webView:currentWebView 
561                                                 createWebViewWithRequest:nil
562                                                           windowFeatures:features];
563     [features release];
564     return core([newWebView mainFrame]);
567 void WebFrameLoaderClient::dispatchShow()
569     WebView *webView = getWebView(m_webFrame.get());
570     [[webView _UIDelegateForwarder] webViewShow:webView];
573 void WebFrameLoaderClient::dispatchDecidePolicyForMIMEType(FramePolicyFunction function,
574     const String& MIMEType, const ResourceRequest& request)
576     WebView *webView = getWebView(m_webFrame.get());
578     [[webView _policyDelegateForwarder] webView:webView
579                         decidePolicyForMIMEType:MIMEType
580                                         request:request.nsURLRequest()
581                                           frame:m_webFrame.get()
582                                decisionListener:setUpPolicyListener(function).get()];
585 void WebFrameLoaderClient::dispatchDecidePolicyForNewWindowAction(FramePolicyFunction function,
586     const NavigationAction& action, const ResourceRequest& request, PassRefPtr<FormState> formState, const String& frameName)
588     WebView *webView = getWebView(m_webFrame.get());
589     [[webView _policyDelegateForwarder] webView:webView
590             decidePolicyForNewWindowAction:actionDictionary(action, formState)
591                                    request:request.nsURLRequest()
592                               newFrameName:frameName
593                           decisionListener:setUpPolicyListener(function).get()];
596 void WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction(FramePolicyFunction function,
597     const NavigationAction& action, const ResourceRequest& request, PassRefPtr<FormState> formState)
599     WebView *webView = getWebView(m_webFrame.get());
600     [[webView _policyDelegateForwarder] webView:webView
601                 decidePolicyForNavigationAction:actionDictionary(action, formState)
602                                         request:request.nsURLRequest()
603                                           frame:m_webFrame.get()
604                                decisionListener:setUpPolicyListener(function).get()];
607 void WebFrameLoaderClient::cancelPolicyCheck()
609     [m_policyListener.get() invalidate];
610     m_policyListener = nil;
611     m_policyFunction = 0;
614 void WebFrameLoaderClient::dispatchUnableToImplementPolicy(const ResourceError& error)
616     WebView *webView = getWebView(m_webFrame.get());
617     [[webView _policyDelegateForwarder] webView:webView unableToImplementPolicyWithError:error frame:m_webFrame.get()];    
620 void WebFrameLoaderClient::dispatchWillSubmitForm(FramePolicyFunction function, PassRefPtr<FormState> formState)
622     id <WebFormDelegate> formDelegate = [getWebView(m_webFrame.get()) _formDelegate];
623     if (!formDelegate) {
624         (core(m_webFrame.get())->loader()->*function)(PolicyUse);
625         return;
626     }
628     NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] initWithCapacity:formState->values().size()];
629     HashMap<String, String>::const_iterator end = formState->values().end();
630     for (HashMap<String, String>::const_iterator it = formState->values().begin(); it != end; ++it)
631         [dictionary setObject:it->second forKey:it->first];
633     CallFormDelegate(getWebView(m_webFrame.get()), @selector(frame:sourceFrame:willSubmitForm:withValues:submissionListener:), m_webFrame.get(), kit(formState->sourceFrame()), kit(formState->form()), dictionary, setUpPolicyListener(function).get());
635     [dictionary release];
638 void WebFrameLoaderClient::dispatchDidLoadMainResource(DocumentLoader* loader)
642 void WebFrameLoaderClient::revertToProvisionalState(DocumentLoader* loader)
644     [dataSource(loader) _revertToProvisionalState];
647 void WebFrameLoaderClient::setMainDocumentError(DocumentLoader* loader, const ResourceError& error)
649     [dataSource(loader) _setMainDocumentError:error];
652 void WebFrameLoaderClient::willChangeEstimatedProgress()
654     [getWebView(m_webFrame.get()) _willChangeValueForKey:_WebEstimatedProgressKey];
657 void WebFrameLoaderClient::didChangeEstimatedProgress()
659     [getWebView(m_webFrame.get()) _didChangeValueForKey:_WebEstimatedProgressKey];
662 void WebFrameLoaderClient::postProgressStartedNotification()
664     [[NSNotificationCenter defaultCenter] postNotificationName:WebViewProgressStartedNotification object:getWebView(m_webFrame.get())];
667 void WebFrameLoaderClient::postProgressEstimateChangedNotification()
669     [[NSNotificationCenter defaultCenter] postNotificationName:WebViewProgressEstimateChangedNotification object:getWebView(m_webFrame.get())];
672 void WebFrameLoaderClient::postProgressFinishedNotification()
674     [[NSNotificationCenter defaultCenter] postNotificationName:WebViewProgressFinishedNotification object:getWebView(m_webFrame.get())];
677 void WebFrameLoaderClient::setMainFrameDocumentReady(bool ready)
679     [getWebView(m_webFrame.get()) setMainFrameDocumentReady:ready];
682 void WebFrameLoaderClient::startDownload(const ResourceRequest& request)
684     // FIXME: Should download full request.
685     WebDownload *download = [getWebView(m_webFrame.get()) _downloadURL:request.url()];
686     
687     setOriginalURLForDownload(download, request);
690 void WebFrameLoaderClient::willChangeTitle(DocumentLoader* loader)
692     // FIXME: Should do this only in main frame case, right?
693     [getWebView(m_webFrame.get()) _willChangeValueForKey:_WebMainFrameTitleKey];
696 void WebFrameLoaderClient::didChangeTitle(DocumentLoader* loader)
698     // FIXME: Should do this only in main frame case, right?
699     [getWebView(m_webFrame.get()) _didChangeValueForKey:_WebMainFrameTitleKey];
702 void WebFrameLoaderClient::committedLoad(DocumentLoader* loader, const char* data, int length)
704     NSData *nsData = [[NSData alloc] initWithBytesNoCopy:(void*)data length:length freeWhenDone:NO];
705     [dataSource(loader) _receivedData:nsData];
706     [nsData release];
709 void WebFrameLoaderClient::finishedLoading(DocumentLoader* loader)
711     [dataSource(loader) _finishedLoading];
714 void WebFrameLoaderClient::updateGlobalHistory(const KURL& url)
716     NSURL *cocoaURL = url;
717     const String& pageTitle = core(m_webFrame.get())->loader()->documentLoader()->title();
718     [[WebHistory optionalSharedHistory] _visitedURL:cocoaURL withTitle:pageTitle];
721 bool WebFrameLoaderClient::shouldGoToHistoryItem(HistoryItem* item) const
723     WebView* view = getWebView(m_webFrame.get());
724     WebHistoryItem *webItem = kit(item);
725     
726     return [[view _policyDelegateForwarder] webView:view shouldGoToHistoryItem:webItem];
729 ResourceError WebFrameLoaderClient::cancelledError(const ResourceRequest& request)
731     return [NSError _webKitErrorWithDomain:NSURLErrorDomain code:NSURLErrorCancelled URL:request.url()];
733     
734 ResourceError WebFrameLoaderClient::blockedError(const ResourceRequest& request)
736     return [NSError _webKitErrorWithDomain:WebKitErrorDomain code:WebKitErrorCannotUseRestrictedPort URL:request.url()];
739 ResourceError WebFrameLoaderClient::cannotShowURLError(const ResourceRequest& request)
741     return [NSError _webKitErrorWithDomain:WebKitErrorDomain code:WebKitErrorCannotShowURL URL:request.url()];
744 ResourceError WebFrameLoaderClient::interruptForPolicyChangeError(const ResourceRequest& request)
746     return [NSError _webKitErrorWithDomain:WebKitErrorDomain code:WebKitErrorFrameLoadInterruptedByPolicyChange URL:request.url()];
749 ResourceError WebFrameLoaderClient::cannotShowMIMETypeError(const ResourceResponse& response)
751     return [NSError _webKitErrorWithDomain:NSURLErrorDomain code:WebKitErrorCannotShowMIMEType URL:response.url()];
754 ResourceError WebFrameLoaderClient::fileDoesNotExistError(const ResourceResponse& response)
756     return [NSError _webKitErrorWithDomain:NSURLErrorDomain code:NSURLErrorFileDoesNotExist URL:response.url()];    
759 ResourceError WebFrameLoaderClient::pluginWillHandleLoadError(const ResourceResponse& response)
761     NSError *error = [[NSError alloc] _initWithPluginErrorCode:WebKitErrorPlugInWillHandleLoad
762                                                     contentURL:response.url()
763                                                  pluginPageURL:nil
764                                                     pluginName:nil
765                                                       MIMEType:response.mimeType()];
766     return [error autorelease];
769 bool WebFrameLoaderClient::shouldFallBack(const ResourceError& error)
771     // FIXME: Needs to check domain.
772     // FIXME: WebKitErrorPlugInWillHandleLoad is a workaround for the cancel we do to prevent
773     // loading plugin content twice.  See <rdar://problem/4258008>
774     return error.errorCode() != NSURLErrorCancelled && error.errorCode() != WebKitErrorPlugInWillHandleLoad;
777 bool WebFrameLoaderClient::canHandleRequest(const ResourceRequest& request) const
779     Frame* frame = core(m_webFrame.get());
780     Page* page = frame->page();
781     BOOL forMainFrame = page && page->mainFrame() == frame;
782     return [WebView _canHandleRequest:request.nsURLRequest() forMainFrame:forMainFrame];
785 bool WebFrameLoaderClient::canShowMIMEType(const String& MIMEType) const
787     return [WebView canShowMIMEType:MIMEType];
790 bool WebFrameLoaderClient::representationExistsForURLScheme(const String& URLScheme) const
792     return [WebView _representationExistsForURLScheme:URLScheme];
795 String WebFrameLoaderClient::generatedMIMETypeForURLScheme(const String& URLScheme) const
797     return [WebView _generatedMIMETypeForURLScheme:URLScheme];
800 void WebFrameLoaderClient::frameLoadCompleted()
802     // Note: Can be called multiple times.
803     // Even if already complete, we might have set a previous item on a frame that
804     // didn't do any data loading on the past transaction. Make sure to clear these out.
805     NSScrollView *sv = [m_webFrame->_private->webFrameView _scrollView];
806     if ([getWebView(m_webFrame.get()) drawsBackground])
807         [sv setDrawsBackground:YES];
808     core(m_webFrame.get())->loader()->setPreviousHistoryItem(0);
812 void WebFrameLoaderClient::saveViewStateToItem(HistoryItem* item)
814     if (!item)
815         return;
816     
817     NSView <WebDocumentView> *docView = [m_webFrame->_private->webFrameView documentView];
819     // we might already be detached when this is called from detachFromParent, in which
820     // case we don't want to override real data earlier gathered with (0,0)
821     if ([docView superview] && [docView conformsToProtocol:@protocol(_WebDocumentViewState)])
822         item->setViewState([(id <_WebDocumentViewState>)docView viewState]);
825 void WebFrameLoaderClient::restoreViewState()
827     HistoryItem* currentItem = core(m_webFrame.get())->loader()->currentHistoryItem();
828     ASSERT(currentItem);
830     // FIXME: As the ASSERT attests, it seems we should always have a currentItem here.
831     // One counterexample is <rdar://problem/4917290>
832     // For now, to cover this issue in release builds, there is no technical harm to returning
833     // early and from a user standpoint - as in the above radar - the previous page load failed 
834     // so there *is* no scroll state to restore!
835     if (!currentItem)
836         return;
837     
838     NSView <WebDocumentView> *docView = [m_webFrame->_private->webFrameView documentView];
839     if ([docView conformsToProtocol:@protocol(_WebDocumentViewState)]) {        
840         id state = currentItem->viewState();
841         if (state) {
842             [(id <_WebDocumentViewState>)docView setViewState:state];
843         }
844     }
847 void WebFrameLoaderClient::provisionalLoadStarted()
848 {    
849     // FIXME: This is OK as long as no one resizes the window,
850     // but in the case where someone does, it means garbage outside
851     // the occupied part of the scroll view.
852     [[m_webFrame->_private->webFrameView _scrollView] setDrawsBackground:NO];
855 void WebFrameLoaderClient::didFinishLoad()
857     [m_webFrame->_private->internalLoadDelegate webFrame:m_webFrame.get() didFinishLoadWithError:nil];    
860 void WebFrameLoaderClient::prepareForDataSourceReplacement()
862     if (![m_webFrame.get() _dataSource]) {
863         ASSERT(!core(m_webFrame.get())->tree()->childCount());
864         return;
865     }
866     
867     // Make sure that any work that is triggered by resigning first reponder can get done.
868     // The main example where this came up is the textDidEndEditing that is sent to the
869     // FormsDelegate (3223413). We need to do this before _detachChildren, since that will
870     // remove the views as a side-effect of freeing the frame, at which point we can't
871     // post the FormDelegate messages.
872     //
873     // Note that this can also take FirstResponder away from a child of our frameView that
874     // is not in a child frame's view.  This is OK because we are in the process
875     // of loading new content, which will blow away all editors in this top frame, and if
876     // a non-editor is firstReponder it will not be affected by endEditingFor:.
877     // Potentially one day someone could write a DocView whose editors were not all
878     // replaced by loading new content, but that does not apply currently.
879     NSView *frameView = m_webFrame->_private->webFrameView;
880     NSWindow *window = [frameView window];
881     NSResponder *firstResp = [window firstResponder];
882     if ([firstResp isKindOfClass:[NSView class]] && [(NSView *)firstResp isDescendantOf:frameView])
883         [window endEditingFor:firstResp];
886 PassRefPtr<DocumentLoader> WebFrameLoaderClient::createDocumentLoader(const ResourceRequest& request, const SubstituteData& substituteData)
888     RefPtr<WebDocumentLoaderMac> loader = WebDocumentLoaderMac::create(request, substituteData);
890     WebDataSource *dataSource = [[WebDataSource alloc] _initWithDocumentLoader:loader.get()];
891     loader->setDataSource(dataSource, getWebView(m_webFrame.get()));
892     [dataSource release];
894     return loader.release();
897 // FIXME: <rdar://problem/4880065> - Push Global History into WebCore
898 // Once that task is complete, this will go away
899 void WebFrameLoaderClient::setTitle(const String& title, const KURL& URL)
901     NSURL* nsURL = URL;
902     nsURL = [nsURL _webkit_canonicalize];
903     if(!nsURL)
904         return;
905     NSString *titleNSString = title;
906     [[[WebHistory optionalSharedHistory] itemForURL:nsURL] setTitle:titleNSString];
909 void WebFrameLoaderClient::savePlatformDataToCachedPage(CachedPage* cachedPage)
911     WebCachedPagePlatformData* webPlatformData = new WebCachedPagePlatformData([m_webFrame->_private->webFrameView documentView]);
912     cachedPage->setCachedPagePlatformData(webPlatformData);
915 void WebFrameLoaderClient::transitionToCommittedFromCachedPage(CachedPage* cachedPage)
917     WebCachedPagePlatformData* platformData = reinterpret_cast<WebCachedPagePlatformData*>(cachedPage->cachedPagePlatformData());
918     NSView <WebDocumentView> *cachedView = platformData->webDocumentView();
919     ASSERT(cachedView != nil);
920     ASSERT(cachedPage->documentLoader());
921     [cachedView setDataSource:dataSource(cachedPage->documentLoader())];
922     
923     // clean up webkit plugin instances before WebHTMLView gets freed.
924     WebView *webView = getWebView(m_webFrame.get());
925     [webView removePluginInstanceViewsFor:(m_webFrame.get())];
926     
927     [m_webFrame->_private->webFrameView _setDocumentView:cachedView];
930 void WebFrameLoaderClient::transitionToCommittedForNewPage()
932     WebFrameView *v = m_webFrame->_private->webFrameView;
933     WebDataSource *ds = [m_webFrame.get() _dataSource];
935     bool willProduceHTMLView = [[WebFrameView class] _viewClassForMIMEType:[ds _responseMIMEType]] == [WebHTMLView class];
936     bool canSkipCreation = core(m_webFrame.get())->loader()->committingFirstRealLoad() && willProduceHTMLView;
937     if (canSkipCreation) {
938         [[v documentView] setDataSource:ds];
939         return;
940     }
942     // Don't suppress scrollbars before the view creation if we're making the view for a non-HTML view.
943     if (!willProduceHTMLView)
944         [[v _scrollView] setScrollBarsSuppressed:NO repaintOnUnsuppress:NO];
945     
946     // clean up webkit plugin instances before WebHTMLView gets freed.
947     WebView *webView = getWebView(m_webFrame.get());
948     [webView removePluginInstanceViewsFor:(m_webFrame.get())];
949     
950     BOOL useDocumentViews = [webView _usesDocumentViews];
951     NSView <WebDocumentView> *documentView = nil;
952     if (useDocumentViews) {
953         documentView = [v _makeDocumentViewForDataSource:ds];
954         if (!documentView)
955             return;
956     }
958     // FIXME: Could we skip some of this work for a top-level view that is not a WebHTMLView?
960     // If we own the view, delete the old one - otherwise the render m_frame will take care of deleting the view.
961     Frame* coreFrame = core(m_webFrame.get());
962     Page* page = coreFrame->page();
963     bool isMainFrame = coreFrame == page->mainFrame();
964     if (isMainFrame && coreFrame->view())
965         coreFrame->view()->setParentVisible(false);
966     coreFrame->setView(0);
967     FrameView* coreView;
968     if (useDocumentViews)
969         coreView = new FrameView(coreFrame);
970     else
971         coreView = new FrameView(coreFrame, IntSize([webView bounds].size));
972     coreFrame->setView(coreView);
973     coreView->deref(); // FIXME: Eliminate this crazy refcounting!
975     [m_webFrame.get() _updateBackgroundAndUpdatesWhileOffscreen];
977     [v _install];
979     if (isMainFrame)
980         coreView->setParentVisible(true);
982     // Call setDataSource on the document view after it has been placed in the view hierarchy.
983     // This what we for the top-level view, so should do this for views in subframes as well.
984     [documentView setDataSource:ds];
985     
986     if (HTMLFrameOwnerElement* owner = coreFrame->ownerElement())
987         coreFrame->view()->setCanHaveScrollbars(owner->scrollingMode() != ScrollbarAlwaysOff);
988     
991 RetainPtr<WebFramePolicyListener> WebFrameLoaderClient::setUpPolicyListener(FramePolicyFunction function)
993     // FIXME: <rdar://5634381> We need to support multiple active policy listeners.
995     [m_policyListener.get() invalidate];
997     WebFramePolicyListener *listener = [[WebFramePolicyListener alloc] initWithWebCoreFrame:core(m_webFrame.get())];
998     m_policyListener = listener;
999     [listener release];
1000     m_policyFunction = function;
1002     return listener;
1005 void WebFrameLoaderClient::receivedPolicyDecison(PolicyAction action)
1007     ASSERT(m_policyListener);
1008     ASSERT(m_policyFunction);
1010     FramePolicyFunction function = m_policyFunction;
1012     m_policyListener = nil;
1013     m_policyFunction = 0;
1015     (core(m_webFrame.get())->loader()->*function)(action);
1018 String WebFrameLoaderClient::userAgent(const KURL& url)
1020     WebView *webView = getWebView(m_webFrame.get());
1021     ASSERT(webView);
1023     // We should never get here with nil for the WebView unless there is a bug somewhere else.
1024     // But if we do, it's better to return the empty string than just crashing on the spot.
1025     // Most other call sites are tolerant of nil because of Objective-C behavior, but this one
1026     // is not because the return value of _userAgentForURL is a const KURL&.
1027     if (!webView)
1028         return String("");
1030     return [webView _userAgentForURL:url];
1033 static const MouseEvent* findMouseEvent(const Event* event)
1035     for (const Event* e = event; e; e = e->underlyingEvent())
1036         if (e->isMouseEvent())
1037             return static_cast<const MouseEvent*>(e);
1038     return 0;
1041 NSDictionary *WebFrameLoaderClient::actionDictionary(const NavigationAction& action, PassRefPtr<FormState> formState) const
1043     unsigned modifierFlags = 0;
1044     const Event* event = action.event();
1045     if (const UIEventWithKeyState* keyStateEvent = findEventWithKeyState(const_cast<Event*>(event))) {
1046         if (keyStateEvent->ctrlKey())
1047             modifierFlags |= NSControlKeyMask;
1048         if (keyStateEvent->altKey())
1049             modifierFlags |= NSAlternateKeyMask;
1050         if (keyStateEvent->shiftKey())
1051             modifierFlags |= NSShiftKeyMask;
1052         if (keyStateEvent->metaKey())
1053             modifierFlags |= NSCommandKeyMask;
1054     }
1056     NSURL *originalURL = action.url();
1058     NSMutableDictionary *result = [NSMutableDictionary dictionaryWithObjectsAndKeys:
1059         [NSNumber numberWithInt:action.type()], WebActionNavigationTypeKey,
1060         [NSNumber numberWithInt:modifierFlags], WebActionModifierFlagsKey,
1061         originalURL, WebActionOriginalURLKey,
1062         nil];
1064     if (const MouseEvent* mouseEvent = findMouseEvent(event)) {
1065         IntPoint point(mouseEvent->pageX(), mouseEvent->pageY());
1066         WebElementDictionary *element = [[WebElementDictionary alloc]
1067             initWithHitTestResult:core(m_webFrame.get())->eventHandler()->hitTestResultAtPoint(point, false)];
1068         [result setObject:element forKey:WebActionElementKey];
1069         [element release];
1071         [result setObject:[NSNumber numberWithInt:mouseEvent->button()] forKey:WebActionButtonKey];
1072     }
1074     if (formState) {
1075         ASSERT(formState->form());
1076         [result setObject:kit(formState->form()) forKey:WebActionFormKey];
1077     }
1079     return result;
1082 bool WebFrameLoaderClient::canCachePage() const
1084     // We can only cache HTML pages right now
1085     return [[[m_webFrame.get() _dataSource] representation] isKindOfClass:[WebHTMLRepresentation class]];
1088 PassRefPtr<Frame> WebFrameLoaderClient::createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement,
1089     const String& referrer, bool allowsScrolling, int marginWidth, int marginHeight)
1091     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1092     
1093     ASSERT(m_webFrame);
1094     
1095     WebFrameView *childView = [getWebView(m_webFrame.get()) _usesDocumentViews] ? [[WebFrameView alloc] init] : nil;
1096     
1097     RefPtr<Frame> result = [WebFrame _createSubframeWithOwnerElement:ownerElement frameName:name frameView:childView];
1098     [childView release];
1100     WebFrame *newFrame = kit(result.get());
1102     if ([newFrame _dataSource])
1103         [[newFrame _dataSource] _documentLoader]->setOverrideEncoding([[m_webFrame.get() _dataSource] _documentLoader]->overrideEncoding());  
1105     // The creation of the frame may have run arbitrary JavaScript that removed it from the page already.
1106     if (!result->page())
1107         return 0;
1109     core(m_webFrame.get())->loader()->loadURLIntoChildFrame(url, referrer, result.get());
1111     // The frame's onload handler may have removed it from the document.
1112     if (!result->tree()->parent())
1113         return 0;
1115     return result.release();
1117     END_BLOCK_OBJC_EXCEPTIONS;
1119     return 0;
1122 ObjectContentType WebFrameLoaderClient::objectContentType(const KURL& url, const String& mimeType)
1124     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1126     // This is a quirk that ensures Tiger Mail's WebKit plug-in will load during layout
1127     // and not attach time. (5520541)
1128     static BOOL isTigerMail = WKAppVersionCheckLessThan(@"com.apple.mail", -1, 3.0);
1129     if (isTigerMail && mimeType == "application/x-apple-msg-attachment")
1130         return ObjectContentNetscapePlugin;
1132     String type = mimeType;
1134     if (type.isEmpty()) {
1135         // Try to guess the MIME type based off the extension.
1136         NSURL *URL = url;
1137         NSString *extension = [[URL path] pathExtension];
1138         if ([extension length] > 0) {
1139             type = WKGetMIMETypeForExtension(extension);
1140             if (type.isEmpty()) {
1141                 // If no MIME type is specified, use a plug-in if we have one that can handle the extension.
1142                 if (WebBasePluginPackage *package = [getWebView(m_webFrame.get()) _pluginForExtension:extension]) {
1143                     if ([package isKindOfClass:[WebPluginPackage class]]) 
1144                         return ObjectContentOtherPlugin;
1145 #if ENABLE(NETSCAPE_PLUGIN_API)
1146                     else {
1147                         ASSERT([package isKindOfClass:[WebNetscapePluginPackage class]]);
1148                         return ObjectContentNetscapePlugin;
1149                     }
1150 #endif
1151                 }
1152             }
1153         }
1154     }
1156     if (type.isEmpty())
1157         return ObjectContentFrame; // Go ahead and hope that we can display the content.
1159     if (MIMETypeRegistry::isSupportedImageMIMEType(type))
1160         return ObjectContentImage;
1162     WebBasePluginPackage *package = [getWebView(m_webFrame.get()) _pluginForMIMEType:type];
1163     if (package) {
1164 #if ENABLE(NETSCAPE_PLUGIN_API)
1165         if ([package isKindOfClass:[WebNetscapePluginPackage class]])
1166             return ObjectContentNetscapePlugin;
1167 #endif
1168         ASSERT([package isKindOfClass:[WebPluginPackage class]]);
1169         return ObjectContentOtherPlugin;
1170     }
1172     if ([WebFrameView _viewClassForMIMEType:type])
1173         return ObjectContentFrame;
1174     
1175     return ObjectContentNone;
1177     END_BLOCK_OBJC_EXCEPTIONS;
1179     return ObjectContentNone;
1182 static NSMutableArray* kit(const Vector<String>& vector)
1184     unsigned len = vector.size();
1185     NSMutableArray* array = [NSMutableArray arrayWithCapacity:len];
1186     for (unsigned x = 0; x < len; x++)
1187         [array addObject:vector[x]];
1188     return array;
1191 static String parameterValue(const Vector<String>& paramNames, const Vector<String>& paramValues, const String& name)
1193     size_t size = paramNames.size();
1194     ASSERT(size == paramValues.size());
1195     for (size_t i = 0; i < size; ++i) {
1196         if (equalIgnoringCase(paramNames[i], name))
1197             return paramValues[i];
1198     }
1199     return String();
1202 static NSView *pluginView(WebFrame *frame, WebPluginPackage *pluginPackage,
1203     NSArray *attributeNames, NSArray *attributeValues, NSURL *baseURL,
1204     DOMElement *element, BOOL loadManually)
1206     WebHTMLView *docView = (WebHTMLView *)[[frame frameView] documentView];
1207     ASSERT([docView isKindOfClass:[WebHTMLView class]]);
1208         
1209     WebPluginController *pluginController = [docView _pluginController];
1210     
1211     // Store attributes in a dictionary so they can be passed to WebPlugins.
1212     NSMutableDictionary *attributes = [[NSMutableDictionary alloc] initWithObjects:attributeValues forKeys:attributeNames];
1213     
1214     [pluginPackage load];
1215     Class viewFactory = [pluginPackage viewFactory];
1216     
1217     NSView *view = nil;
1218     NSDictionary *arguments = nil;
1219     
1220     if ([viewFactory respondsToSelector:@selector(plugInViewWithArguments:)]) {
1221         arguments = [NSDictionary dictionaryWithObjectsAndKeys:
1222             baseURL, WebPlugInBaseURLKey,
1223             attributes, WebPlugInAttributesKey,
1224             pluginController, WebPlugInContainerKey,
1225             [NSNumber numberWithInt:loadManually ? WebPlugInModeFull : WebPlugInModeEmbed], WebPlugInModeKey,
1226             [NSNumber numberWithBool:!loadManually], WebPlugInShouldLoadMainResourceKey,
1227             element, WebPlugInContainingElementKey,
1228             nil];
1229         LOG(Plugins, "arguments:\n%@", arguments);
1230     } else if ([viewFactory respondsToSelector:@selector(pluginViewWithArguments:)]) {
1231         arguments = [NSDictionary dictionaryWithObjectsAndKeys:
1232             baseURL, WebPluginBaseURLKey,
1233             attributes, WebPluginAttributesKey,
1234             pluginController, WebPluginContainerKey,
1235             element, WebPlugInContainingElementKey,
1236             nil];
1237         LOG(Plugins, "arguments:\n%@", arguments);
1238     }
1240     view = [WebPluginController plugInViewWithArguments:arguments fromPluginPackage:pluginPackage];
1241     [attributes release];
1242     return view;
1245 class PluginWidget : public Widget {
1246 public:
1247     PluginWidget(NSView *view = 0)
1248         : Widget(view)
1249     {
1250     }
1251     
1252     virtual void invalidateRect(const IntRect& rect)
1253     {
1254         [platformWidget() setNeedsDisplayInRect:rect];
1255     }
1258 #if ENABLE(NETSCAPE_PLUGIN_API)
1260 class NetscapePluginWidget : public PluginWidget {
1261 public:
1262     NetscapePluginWidget(WebBaseNetscapePluginView *view)
1263         : PluginWidget(view)
1264     {
1265     }
1266     
1267     virtual void handleEvent(Event*)
1268     {
1269         Frame* frame = Frame::frameForWidget(this);
1270         if (!frame)
1271             return;
1272         
1273         NSEvent* event = frame->eventHandler()->currentNSEvent();
1274         if ([event type] == NSMouseMoved)
1275             [(WebBaseNetscapePluginView *)platformWidget() handleMouseMoved:event];
1276     }
1277     
1280 #endif // ENABLE(NETSCAPE_PLUGIN_API)
1282 Widget* WebFrameLoaderClient::createPlugin(const IntSize& size, Element* element, const KURL& url,
1283     const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually)
1285     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1287     ASSERT(paramNames.size() == paramValues.size());
1289     int errorCode = 0;
1291     WebView *webView = getWebView(m_webFrame.get());
1292     SEL selector = @selector(webView:plugInViewWithArguments:);
1293     NSURL *URL = url;
1295     if ([[webView UIDelegate] respondsToSelector:selector]) {
1296         NSMutableDictionary *attributes = [[NSMutableDictionary alloc] initWithObjects:kit(paramValues) forKeys:kit(paramNames)];
1297         NSDictionary *arguments = [[NSDictionary alloc] initWithObjectsAndKeys:
1298             attributes, WebPlugInAttributesKey,
1299             [NSNumber numberWithInt:loadManually ? WebPlugInModeFull : WebPlugInModeEmbed], WebPlugInModeKey,
1300             [NSNumber numberWithBool:!loadManually], WebPlugInShouldLoadMainResourceKey,
1301             kit(element), WebPlugInContainingElementKey,
1302             URL, WebPlugInBaseURLKey, // URL might be nil, so add it last
1303             nil];
1305         NSView *view = CallUIDelegate(webView, selector, arguments);
1307         [attributes release];
1308         [arguments release];
1310         if (view)
1311             return new PluginWidget(view);
1312     }
1314     NSString *MIMEType;
1315     WebBasePluginPackage *pluginPackage;
1316     if (mimeType.isEmpty()) {
1317         MIMEType = nil;
1318         pluginPackage = nil;
1319     } else {
1320         MIMEType = mimeType;
1321         pluginPackage = [webView _pluginForMIMEType:mimeType];
1322     }
1323     
1324     NSString *extension = [[URL path] pathExtension];
1325     if (!pluginPackage && [extension length] != 0) {
1326         pluginPackage = [webView _pluginForExtension:extension];
1327         if (pluginPackage) {
1328             NSString *newMIMEType = [pluginPackage MIMETypeForExtension:extension];
1329             if ([newMIMEType length] != 0)
1330                 MIMEType = newMIMEType;
1331         }
1332     }
1334     NSView *view = nil;
1336     Document* document = core(m_webFrame.get())->document();
1337     NSURL *baseURL = document->baseURL();
1338     if (pluginPackage) {
1339         if ([pluginPackage isKindOfClass:[WebPluginPackage class]])
1340             view = pluginView(m_webFrame.get(), (WebPluginPackage *)pluginPackage, kit(paramNames), kit(paramValues), baseURL, kit(element), loadManually);
1341             
1342 #if ENABLE(NETSCAPE_PLUGIN_API)
1343         else if ([pluginPackage isKindOfClass:[WebNetscapePluginPackage class]]) {
1344             WebBaseNetscapePluginView *embeddedView = [[[WebBaseNetscapePluginView alloc]
1345                 initWithFrame:NSMakeRect(0, 0, size.width(), size.height())
1346                 pluginPackage:(WebNetscapePluginPackage *)pluginPackage
1347                 URL:URL
1348                 baseURL:baseURL
1349                 MIMEType:MIMEType
1350                 attributeKeys:kit(paramNames)
1351                 attributeValues:kit(paramValues)
1352                 loadManually:loadManually
1353                 DOMElement:kit(element)] autorelease];
1354             
1355             return new NetscapePluginWidget(embeddedView);
1356         } 
1357 #endif
1358     } else
1359         errorCode = WebKitErrorCannotFindPlugIn;
1361     if (!errorCode && !view)
1362         errorCode = WebKitErrorCannotLoadPlugIn;
1364     if (errorCode) {
1365         NSError *error = [[NSError alloc] _initWithPluginErrorCode:errorCode
1366             contentURL:URL
1367             pluginPageURL:document->completeURL(parseURL(parameterValue(paramNames, paramValues, "pluginspage")))
1368             pluginName:[pluginPackage name]
1369             MIMEType:MIMEType];
1370         WebNullPluginView *nullView = [[[WebNullPluginView alloc] initWithFrame:NSMakeRect(0, 0, size.width(), size.height())
1371             error:error DOMElement:kit(element)] autorelease];
1372         view = nullView;
1373         [error release];
1374     }
1375     
1376     ASSERT(view);
1377     return new PluginWidget(view);
1379     END_BLOCK_OBJC_EXCEPTIONS;
1381     return 0;
1384 void WebFrameLoaderClient::redirectDataToPlugin(Widget* pluginWidget)
1386     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1388     WebHTMLRepresentation *representation = (WebHTMLRepresentation *)[[m_webFrame.get() _dataSource] representation];
1390     NSView *pluginView = pluginWidget->platformWidget();
1392 #if ENABLE(NETSCAPE_PLUGIN_API)
1393     if ([pluginView isKindOfClass:[WebBaseNetscapePluginView class]])
1394         [representation _redirectDataToManualLoader:(WebBaseNetscapePluginView *)pluginView forPluginView:pluginView];
1395     else {
1396 #else
1397     {
1398 #endif
1399         WebHTMLView *documentView = (WebHTMLView *)[[m_webFrame.get() frameView] documentView];
1400         ASSERT([documentView isKindOfClass:[WebHTMLView class]]);
1401         [representation _redirectDataToManualLoader:[documentView _pluginController] forPluginView:pluginView];
1402     }
1404     END_BLOCK_OBJC_EXCEPTIONS;
1406     
1407 Widget* WebFrameLoaderClient::createJavaAppletWidget(const IntSize& size, Element* element, const KURL& baseURL, 
1408     const Vector<String>& paramNames, const Vector<String>& paramValues)
1410     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1412     NSView *view = nil;
1414     NSString *MIMEType = @"application/x-java-applet";
1415     
1416     WebView *webView = getWebView(m_webFrame.get());
1418     WebBasePluginPackage *pluginPackage = [webView _pluginForMIMEType:MIMEType];
1420     if (pluginPackage) {
1421         if ([pluginPackage isKindOfClass:[WebPluginPackage class]]) {
1422             // For some reason, the Java plug-in requires that we pass the dimension of the plug-in as attributes.
1423             NSMutableArray *names = kit(paramNames);
1424             NSMutableArray *values = kit(paramValues);
1425             if (parameterValue(paramNames, paramValues, "width").isNull()) {
1426                 [names addObject:@"width"];
1427                 [values addObject:[NSString stringWithFormat:@"%d", size.width()]];
1428             }
1429             if (parameterValue(paramNames, paramValues, "height").isNull()) {
1430                 [names addObject:@"height"];
1431                 [values addObject:[NSString stringWithFormat:@"%d", size.width()]];
1432             }
1433             view = pluginView(m_webFrame.get(), (WebPluginPackage *)pluginPackage, names, values, baseURL, kit(element), NO);
1434         } 
1435 #if ENABLE(NETSCAPE_PLUGIN_API)
1436         else if ([pluginPackage isKindOfClass:[WebNetscapePluginPackage class]]) {
1437             view = [[[WebBaseNetscapePluginView alloc] initWithFrame:NSMakeRect(0, 0, size.width(), size.height())
1438                 pluginPackage:(WebNetscapePluginPackage *)pluginPackage
1439                 URL:nil
1440                 baseURL:baseURL
1441                 MIMEType:MIMEType
1442                 attributeKeys:kit(paramNames)
1443                 attributeValues:kit(paramValues)
1444                 loadManually:NO
1445                 DOMElement:kit(element)] autorelease];
1446         } else {
1447             ASSERT_NOT_REACHED();
1448         }
1449 #endif
1450     }
1452     if (!view) {
1453         NSError *error = [[NSError alloc] _initWithPluginErrorCode:WebKitErrorJavaUnavailable
1454             contentURL:nil
1455             pluginPageURL:nil
1456             pluginName:[pluginPackage name]
1457             MIMEType:MIMEType];
1458         view = [[[WebNullPluginView alloc] initWithFrame:NSMakeRect(0, 0, size.width(), size.height())
1459             error:error DOMElement:kit(element)] autorelease];
1460         [error release];
1461     }
1463     ASSERT(view);
1464     return new PluginWidget(view);
1466     END_BLOCK_OBJC_EXCEPTIONS;
1467     
1468     return new PluginWidget;
1471 String WebFrameLoaderClient::overrideMediaType() const
1473     NSString* overrideType = [getWebView(m_webFrame.get()) mediaStyle];
1474     if (overrideType)
1475         return overrideType;
1476     return String();
1479 void WebFrameLoaderClient::windowObjectCleared()
1481     Frame *frame = core(m_webFrame.get());
1482     ScriptController *script = frame->script();
1483     WebView *webView = getWebView(m_webFrame.get());
1484     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
1485     if (implementations->didClearWindowObjectForFrameFunc) {
1486         CallFrameLoadDelegate(implementations->didClearWindowObjectForFrameFunc, webView, @selector(webView:didClearWindowObject:forFrame:),
1487             script->windowScriptObject(), m_webFrame.get());
1488     } else if (implementations->windowScriptObjectAvailableFunc) {
1489         CallFrameLoadDelegate(implementations->windowScriptObjectAvailableFunc, webView, @selector(webView:windowScriptObjectAvailable:),
1490             script->windowScriptObject());
1491     }
1493     if ([webView scriptDebugDelegate]) {
1494         [m_webFrame.get() _detachScriptDebugger];
1495         [m_webFrame.get() _attachScriptDebugger];
1496     }
1499 void WebFrameLoaderClient::registerForIconNotification(bool listen)
1501     [[m_webFrame.get() webView] _registerForIconNotification:listen];
1504 void WebFrameLoaderClient::didPerformFirstNavigation() const
1506     WebPreferences *preferences = [[m_webFrame.get() webView] preferences];
1507     if ([preferences automaticallyDetectsCacheModel] && [preferences cacheModel] < WebCacheModelDocumentBrowser)
1508         [preferences setCacheModel:WebCacheModelDocumentBrowser];
1511 #if ENABLE(MAC_JAVA_BRIDGE)
1512 jobject WebFrameLoaderClient::javaApplet(NSView* view)
1514     if ([view respondsToSelector:@selector(webPlugInGetApplet)])
1515         return [view webPlugInGetApplet];
1517     // Compatibility with older versions of Java.
1518     // FIXME: Do we still need this?
1519     if ([view respondsToSelector:@selector(pollForAppletInWindow:)])
1520         return [view pollForAppletInWindow:[[m_webFrame.get() frameView] window]];
1522     return 0;
1524 #endif
1526 @implementation WebFramePolicyListener
1528 #ifndef BUILDING_ON_TIGER
1529 + (void)initialize
1531     WebCoreObjCFinalizeOnMainThread(self);
1533 #endif
1535 - (id)initWithWebCoreFrame:(Frame*)frame
1537     self = [self init];
1538     if (!self)
1539         return nil;
1540     frame->ref();
1541     m_frame = frame;
1542     return self;
1545 - (void)invalidate
1547     if (m_frame) {
1548         m_frame->deref();
1549         m_frame = 0;
1550     }
1553 - (void)dealloc
1555     if (WebCoreObjCScheduleDeallocateOnMainThread([WebFramePolicyListener class], self))
1556         return;
1558     if (m_frame)
1559         m_frame->deref();
1560     [super dealloc];
1563 - (void)finalize
1565     ASSERT_MAIN_THREAD();
1566     if (m_frame)
1567         m_frame->deref();
1568     [super finalize];
1571 - (void)receivedPolicyDecision:(PolicyAction)action
1573     RefPtr<Frame> frame = adoptRef(m_frame);
1574     m_frame = 0;
1575     if (frame)
1576         static_cast<WebFrameLoaderClient*>(frame->loader()->client())->receivedPolicyDecison(action);
1579 - (void)ignore
1581     [self receivedPolicyDecision:PolicyIgnore];
1584 - (void)download
1586     [self receivedPolicyDecision:PolicyDownload];
1589 - (void)use
1591     [self receivedPolicyDecision:PolicyUse];
1594 - (void)continue
1596     [self receivedPolicyDecision:PolicyUse];
1599 @end