2009-10-07 Adam Barth <abarth@webkit.org>
[WebKit-https.git] / WebKit / mac / WebCoreSupport / WebFrameLoaderClient.mm
1 /*
2  * Copyright (C) 2006, 2007, 2008, 2009 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  */
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 "DOMElementInternal.h"
37 #import "WebBackForwardList.h"
38 #import "WebCachedFramePlatformData.h"
39 #import "WebChromeClient.h"
40 #import "WebDataSourceInternal.h"
41 #import "WebDelegateImplementationCaching.h"
42 #import "WebDocumentInternal.h"
43 #import "WebDocumentLoaderMac.h"
44 #import "WebDownloadInternal.h"
45 #import "WebDynamicScrollBarsViewInternal.h"
46 #import "WebElementDictionary.h"
47 #import "WebFormDelegate.h"
48 #import "WebFrameInternal.h"
49 #import "WebFrameLoadDelegate.h"
50 #import "WebFrameViewInternal.h"
51 #import "WebHTMLRepresentationPrivate.h"
52 #import "WebHTMLViewInternal.h"
53 #import "WebHistoryItemInternal.h"
54 #import "WebHistoryInternal.h"
55 #import "WebIconDatabaseInternal.h"
56 #import "WebKitErrorsPrivate.h"
57 #import "WebKitLogging.h"
58 #import "WebKitNSStringExtras.h"
59 #import "WebNavigationData.h"
60 #import "WebNSURLExtras.h"
61 #import "WebNetscapePluginView.h"
62 #import "WebNetscapePluginPackage.h"
63 #import "WebNullPluginView.h"
64 #import "WebPanelAuthenticationHandler.h"
65 #import "WebPluginController.h"
66 #import "WebPluginPackage.h"
67 #import "WebPluginViewFactoryPrivate.h"
68 #import "WebPolicyDelegate.h"
69 #import "WebPolicyDelegatePrivate.h"
70 #import "WebPreferences.h"
71 #import "WebResourceLoadDelegate.h"
72 #import "WebSecurityOriginInternal.h"
73 #import "WebUIDelegate.h"
74 #import "WebUIDelegatePrivate.h"
75 #import "WebViewInternal.h"
76 #import <WebKitSystemInterface.h>
77 #import <WebCore/AuthenticationMac.h>
78 #import <WebCore/BlockExceptions.h>
79 #import <WebCore/CachedFrame.h>
80 #import <WebCore/Chrome.h>
81 #import <WebCore/Document.h>
82 #import <WebCore/DocumentLoader.h>
83 #import <WebCore/EventHandler.h>
84 #import <WebCore/FocusController.h>
85 #import <WebCore/FormState.h>
86 #import <WebCore/Frame.h>
87 #import <WebCore/FrameLoader.h>
88 #import <WebCore/FrameLoaderTypes.h>
89 #import <WebCore/FrameTree.h>
90 #import <WebCore/FrameView.h>
91 #import <WebCore/HTMLAppletElement.h>
92 #import <WebCore/HTMLHeadElement.h>
93 #import <WebCore/HTMLFormElement.h>
94 #import <WebCore/HTMLFrameElement.h>
95 #import <WebCore/HTMLFrameOwnerElement.h>
96 #import <WebCore/HTMLNames.h>
97 #import <WebCore/HTMLPlugInElement.h>
98 #import <WebCore/HistoryItem.h>
99 #import <WebCore/HitTestResult.h>
100 #import <WebCore/IconDatabase.h>
101 #import <WebCore/LoaderNSURLExtras.h>
102 #import <WebCore/MIMETypeRegistry.h>
103 #import <WebCore/MouseEvent.h>
104 #import <WebCore/Page.h>
105 #import <WebCore/PlatformString.h>
106 #import <WebCore/ResourceError.h>
107 #import <WebCore/ResourceHandle.h>
108 #import <WebCore/ResourceLoader.h>
109 #import <WebCore/ResourceRequest.h>
110 #import <WebCore/ScriptController.h>
111 #import <WebCore/ScriptString.h>
112 #import <WebCore/SharedBuffer.h>
113 #import <WebCore/WebCoreObjCExtras.h>
114 #import <WebCore/Widget.h>
115 #import <WebKit/DOMElement.h>
116 #import <WebKit/DOMHTMLFormElement.h>
117 #import <runtime/InitializeThreading.h>
118 #import <wtf/PassRefPtr.h>
119
120 #if ENABLE(MAC_JAVA_BRIDGE)
121 #import "WebJavaPlugIn.h"
122 #endif
123
124 #if USE(PLUGIN_HOST_PROCESS)
125 #import "NetscapePluginHostManager.h"
126 #import "WebHostedNetscapePluginView.h"
127 #endif
128
129 using namespace WebCore;
130 using namespace HTMLNames;
131
132 #if ENABLE(MAC_JAVA_BRIDGE)
133 @interface NSView (WebJavaPluginDetails)
134 - (jobject)pollForAppletInWindow:(NSWindow *)window;
135 @end
136 #endif
137
138 @interface NSURLDownload (WebNSURLDownloadDetails)
139 - (void)_setOriginatingURL:(NSURL *)originatingURL;
140 @end
141
142 // For backwards compatibility with older WebKit plug-ins.
143 NSString *WebPluginBaseURLKey = @"WebPluginBaseURL";
144 NSString *WebPluginAttributesKey = @"WebPluginAttributes";
145 NSString *WebPluginContainerKey = @"WebPluginContainer";
146
147 @interface WebFramePolicyListener : NSObject <WebPolicyDecisionListener, WebFormSubmissionListener> {
148     Frame* m_frame;
149 }
150 - (id)initWithWebCoreFrame:(Frame*)frame;
151 - (void)invalidate;
152 @end
153
154 static inline WebDataSource *dataSource(DocumentLoader* loader)
155 {
156     return loader ? static_cast<WebDocumentLoaderMac*>(loader)->dataSource() : nil;
157 }
158
159 // Quirk for the Apple Dictionary application.
160 //
161 // If a top level frame has a <script> element in its <head> for a script named MainPageJavaScript.js,
162 // then for that frame's document, ignore changes to the scrolling attribute of frames. That script
163 // has a bug in it where it sets the scrolling attribute on frames, and that erroneous scrolling
164 // attribute needs to be ignored to avoid showing extra scroll bars in the window.
165 // This quirk can be removed when Apple Dictionary is fixed (see <rdar://problem/6471058>).
166
167 static void applyAppleDictionaryApplicationQuirkNonInlinePart(WebFrameLoaderClient* client, const ResourceRequest& request)
168 {
169     if (!request.url().isLocalFile())
170         return;
171     if (!request.url().string().endsWith("MainPageJavaScript.js"))
172         return;
173     Frame* frame = core(client->webFrame());
174     if (!frame)
175         return;
176     if (frame->tree()->parent())
177         return;
178     Document* document = frame->document();
179     if (!document)
180         return;
181     HTMLHeadElement* head = document->head();
182     if (!head)
183         return;
184     for (Node* c = head->firstChild(); c; c = c->nextSibling()) {
185         if (c->hasTagName(scriptTag) && static_cast<Element*>(c)->getAttribute(srcAttr) == "MainPageJavaScript.js") {
186             document->setFrameElementsShouldIgnoreScrolling(true);
187             return;
188         }
189     }
190 }
191
192 static inline void applyAppleDictionaryApplicationQuirk(WebFrameLoaderClient* client, const ResourceRequest& request)
193 {
194     // Use a one-time-initialized global variable so we can quickly determine there's nothing to do in
195     // all applications other than Apple Dictionary.
196     static bool isAppleDictionary = [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.Dictionary"];
197     if (isAppleDictionary)
198         applyAppleDictionaryApplicationQuirkNonInlinePart(client, request);
199 }
200
201 WebFrameLoaderClient::WebFrameLoaderClient(WebFrame *webFrame)
202     : m_webFrame(webFrame)
203     , m_policyFunction(0)
204 {
205 }
206
207 void WebFrameLoaderClient::frameLoaderDestroyed()
208 {
209     [m_webFrame.get() _clearCoreFrame];
210     delete this;
211 }
212
213 bool WebFrameLoaderClient::hasWebView() const
214 {
215     return [m_webFrame.get() webView] != nil;
216 }
217
218 void WebFrameLoaderClient::makeRepresentation(DocumentLoader* loader)
219 {
220     [dataSource(loader) _makeRepresentation];
221 }
222
223 bool WebFrameLoaderClient::hasHTMLView() const
224 {
225     if (![getWebView(m_webFrame.get()) _usesDocumentViews]) {
226         // FIXME (Viewless): For now we just assume that all frames have an HTML view
227         return true;
228     }
229     
230     NSView <WebDocumentView> *view = [m_webFrame->_private->webFrameView documentView];
231     return [view isKindOfClass:[WebHTMLView class]];
232 }
233
234 void WebFrameLoaderClient::forceLayout()
235 {
236     NSView <WebDocumentView> *view = [m_webFrame->_private->webFrameView documentView];
237     if ([view isKindOfClass:[WebHTMLView class]])
238         [(WebHTMLView *)view setNeedsToApplyStyles:YES];
239     [view setNeedsLayout:YES];
240     [view layout];
241 }
242
243 void WebFrameLoaderClient::forceLayoutForNonHTML()
244 {
245     WebFrameView *thisView = m_webFrame->_private->webFrameView;
246     if (!thisView) // Viewless mode.
247         return;
248     NSView <WebDocumentView> *thisDocumentView = [thisView documentView];
249     ASSERT(thisDocumentView != nil);
250     
251     // Tell the just loaded document to layout.  This may be necessary
252     // for non-html content that needs a layout message.
253     if (!([[m_webFrame.get() _dataSource] _isDocumentHTML])) {
254         [thisDocumentView setNeedsLayout:YES];
255         [thisDocumentView layout];
256         [thisDocumentView setNeedsDisplay:YES];
257     }
258 }
259
260 void WebFrameLoaderClient::setCopiesOnScroll()
261 {
262     [[[m_webFrame->_private->webFrameView _scrollView] contentView] setCopiesOnScroll:YES];
263 }
264
265 void WebFrameLoaderClient::detachedFromParent2()
266 {
267     //remove any NetScape plugins that are children of this frame because they are about to be detached
268     WebView *webView = getWebView(m_webFrame.get());
269     [webView removePluginInstanceViewsFor:(m_webFrame.get())];
270     [m_webFrame->_private->webFrameView _setWebFrame:nil]; // needed for now to be compatible w/ old behavior
271 }
272
273 void WebFrameLoaderClient::detachedFromParent3()
274 {
275     [m_webFrame->_private->webFrameView release];
276     m_webFrame->_private->webFrameView = nil;
277 }
278
279 void WebFrameLoaderClient::download(ResourceHandle* handle, const ResourceRequest& request, const ResourceRequest& initialRequest, const ResourceResponse& response)
280 {
281     id proxy = handle->releaseProxy();
282     ASSERT(proxy);
283     
284     WebView *webView = getWebView(m_webFrame.get());
285     WebDownload *download = [WebDownload _downloadWithLoadingConnection:handle->connection()
286                                                                 request:request.nsURLRequest()
287                                                                response:response.nsURLResponse()
288                                                                delegate:[webView downloadDelegate]
289                                                                   proxy:proxy];
290     
291     setOriginalURLForDownload(download, initialRequest);    
292 }
293
294 void WebFrameLoaderClient::setOriginalURLForDownload(WebDownload *download, const ResourceRequest& initialRequest) const
295 {
296     NSURLRequest *initialURLRequest = initialRequest.nsURLRequest();
297     NSURL *originalURL = nil;
298     
299     // If there was no referrer, don't traverse the back/forward history
300     // since this download was initiated directly. <rdar://problem/5294691>
301     if ([initialURLRequest valueForHTTPHeaderField:@"Referer"]) {
302         // find the first item in the history that was originated by the user
303         WebView *webView = getWebView(m_webFrame.get());
304         WebBackForwardList *history = [webView backForwardList];
305         int backListCount = [history backListCount];
306         for (int backIndex = 0; backIndex <= backListCount && !originalURL; backIndex++) {
307             // FIXME: At one point we had code here to check a "was user gesture" flag.
308             // Do we need to restore that logic?
309             originalURL = [[history itemAtIndex:-backIndex] URL];
310         }
311     }
312
313     if (!originalURL)
314         originalURL = [initialURLRequest URL];
315
316     if ([download respondsToSelector:@selector(_setOriginatingURL:)]) {
317         NSString *scheme = [originalURL scheme];
318         NSString *host = [originalURL host];
319         if (scheme && host && [scheme length] && [host length]) {
320             NSNumber *port = [originalURL port];
321             if (port && [port intValue] < 0)
322                 port = nil;
323             NSString *hostOnlyURLString;
324             if (port)
325                 hostOnlyURLString = [[NSString alloc] initWithFormat:@"%@://%@:%d", scheme, host, [port intValue]];
326             else
327                 hostOnlyURLString = [[NSString alloc] initWithFormat:@"%@://%@", scheme, host];
328             NSURL *hostOnlyURL = [[NSURL alloc] initWithString:hostOnlyURLString];
329             [hostOnlyURLString release];
330             [download _setOriginatingURL:hostOnlyURL];
331             [hostOnlyURL release];
332         }
333     }
334 }
335
336 bool WebFrameLoaderClient::dispatchDidLoadResourceFromMemoryCache(DocumentLoader* loader, const ResourceRequest& request, const ResourceResponse& response, int length)
337 {
338     applyAppleDictionaryApplicationQuirk(this, request);
339
340     WebView *webView = getWebView(m_webFrame.get());
341     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
342     if (!implementations->didLoadResourceFromMemoryCacheFunc)
343         return false;
344
345     CallResourceLoadDelegate(implementations->didLoadResourceFromMemoryCacheFunc, webView, @selector(webView:didLoadResourceFromMemoryCache:response:length:fromDataSource:), request.nsURLRequest(), response.nsURLResponse(), length, dataSource(loader));
346     return true;
347 }
348
349 void WebFrameLoaderClient::dispatchDidLoadResourceByXMLHttpRequest(unsigned long identifier, const ScriptString& sourceString)
350 {
351 }
352
353 void WebFrameLoaderClient::assignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader* loader, const ResourceRequest& request)
354 {
355     WebView *webView = getWebView(m_webFrame.get());
356     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
357
358     id object = nil;
359     BOOL shouldRelease = NO;
360     if (implementations->identifierForRequestFunc)
361         object = CallResourceLoadDelegate(implementations->identifierForRequestFunc, webView, @selector(webView:identifierForInitialRequest:fromDataSource:), request.nsURLRequest(), dataSource(loader));
362     else {
363         object = [[NSObject alloc] init];
364         shouldRelease = YES;
365     }
366
367     [webView _addObject:object forIdentifier:identifier];
368
369     if (shouldRelease)
370         [object release];
371 }
372
373 void WebFrameLoaderClient::dispatchWillSendRequest(DocumentLoader* loader, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse)
374 {
375     applyAppleDictionaryApplicationQuirk(this, request);
376
377     WebView *webView = getWebView(m_webFrame.get());
378     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
379
380     if (redirectResponse.isNull())
381         static_cast<WebDocumentLoaderMac*>(loader)->increaseLoadCount(identifier);
382
383     if (implementations->willSendRequestFunc)
384         request = (NSURLRequest *)CallResourceLoadDelegate(implementations->willSendRequestFunc, webView, @selector(webView:resource:willSendRequest:redirectResponse:fromDataSource:), [webView _objectForIdentifier:identifier], request.nsURLRequest(), redirectResponse.nsURLResponse(), dataSource(loader));
385 }
386
387 bool WebFrameLoaderClient::shouldUseCredentialStorage(DocumentLoader* loader, unsigned long identifier)
388 {
389     WebView *webView = getWebView(m_webFrame.get());
390     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
391
392     if (implementations->shouldUseCredentialStorageFunc) {
393         if (id resource = [webView _objectForIdentifier:identifier])
394             return CallResourceLoadDelegateReturningBoolean(NO, implementations->shouldUseCredentialStorageFunc, webView, @selector(webView:resource:shouldUseCredentialStorageForDataSource:), resource, dataSource(loader));
395     }
396
397     return true;
398 }
399
400 void WebFrameLoaderClient::dispatchDidReceiveAuthenticationChallenge(DocumentLoader* loader, unsigned long identifier, const AuthenticationChallenge& challenge)
401 {
402     WebView *webView = getWebView(m_webFrame.get());
403     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
404
405     NSURLAuthenticationChallenge *webChallenge = mac(challenge);
406
407     if (implementations->didReceiveAuthenticationChallengeFunc) {
408         if (id resource = [webView _objectForIdentifier:identifier]) {
409             CallResourceLoadDelegate(implementations->didReceiveAuthenticationChallengeFunc, webView, @selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:), resource, webChallenge, dataSource(loader));
410             return;
411         }
412     }
413
414     NSWindow *window = [webView hostWindow] ? [webView hostWindow] : [webView window];
415     [[WebPanelAuthenticationHandler sharedHandler] startAuthentication:webChallenge window:window];
416 }
417
418 void WebFrameLoaderClient::dispatchDidCancelAuthenticationChallenge(DocumentLoader* loader, unsigned long identifier, const AuthenticationChallenge&challenge)
419 {
420     WebView *webView = getWebView(m_webFrame.get());
421     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
422     NSURLAuthenticationChallenge *webChallenge = mac(challenge);
423
424     if (implementations->didCancelAuthenticationChallengeFunc) {
425         if (id resource = [webView _objectForIdentifier:identifier]) {
426             CallResourceLoadDelegate(implementations->didCancelAuthenticationChallengeFunc, webView, @selector(webView:resource:didCancelAuthenticationChallenge:fromDataSource:), resource, webChallenge, dataSource(loader));
427             return;
428         }
429     }
430
431     [(WebPanelAuthenticationHandler *)[WebPanelAuthenticationHandler sharedHandler] cancelAuthentication:webChallenge];
432 }
433
434 void WebFrameLoaderClient::dispatchDidReceiveResponse(DocumentLoader* loader, unsigned long identifier, const ResourceResponse& response)
435 {
436     WebView *webView = getWebView(m_webFrame.get());
437     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
438     if (implementations->didReceiveResponseFunc) {
439         if (id resource = [webView _objectForIdentifier:identifier])
440             CallResourceLoadDelegate(implementations->didReceiveResponseFunc, webView, @selector(webView:resource:didReceiveResponse:fromDataSource:), resource, response.nsURLResponse(), dataSource(loader));
441     }
442 }
443
444 NSCachedURLResponse* WebFrameLoaderClient::willCacheResponse(DocumentLoader* loader, unsigned long identifier, NSCachedURLResponse* response) const
445 {
446     WebView *webView = getWebView(m_webFrame.get());
447     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
448
449     if (implementations->willCacheResponseFunc) {
450         if (id resource = [webView _objectForIdentifier:identifier])
451             return CallResourceLoadDelegate(implementations->willCacheResponseFunc, webView, @selector(webView:resource:willCacheResponse:fromDataSource:), resource, response, dataSource(loader));
452     }
453
454     return response;
455 }
456
457 void WebFrameLoaderClient::dispatchDidReceiveContentLength(DocumentLoader* loader, unsigned long identifier, int lengthReceived)
458 {
459     WebView *webView = getWebView(m_webFrame.get());
460     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
461     if (implementations->didReceiveContentLengthFunc) {
462         if (id resource = [webView _objectForIdentifier:identifier])
463             CallResourceLoadDelegate(implementations->didReceiveContentLengthFunc, webView, @selector(webView:resource:didReceiveContentLength:fromDataSource:), resource, (NSInteger)lengthReceived, dataSource(loader));
464     }
465 }
466
467 void WebFrameLoaderClient::dispatchDidFinishLoading(DocumentLoader* loader, unsigned long identifier)
468 {
469     WebView *webView = getWebView(m_webFrame.get());
470     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
471
472     if (implementations->didFinishLoadingFromDataSourceFunc) {
473         if (id resource = [webView _objectForIdentifier:identifier])
474             CallResourceLoadDelegate(implementations->didFinishLoadingFromDataSourceFunc, webView, @selector(webView:resource:didFinishLoadingFromDataSource:), resource, dataSource(loader));
475     }
476
477     [webView _removeObjectForIdentifier:identifier];
478
479     static_cast<WebDocumentLoaderMac*>(loader)->decreaseLoadCount(identifier);
480 }
481
482 void WebFrameLoaderClient::dispatchDidFailLoading(DocumentLoader* loader, unsigned long identifier, const ResourceError& error)
483 {
484     WebView *webView = getWebView(m_webFrame.get());
485     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
486
487     if (implementations->didFailLoadingWithErrorFromDataSourceFunc) {
488         if (id resource = [webView _objectForIdentifier:identifier])
489             CallResourceLoadDelegate(implementations->didFailLoadingWithErrorFromDataSourceFunc, webView, @selector(webView:resource:didFailLoadingWithError:fromDataSource:), resource, (NSError *)error, dataSource(loader));
490     }
491
492     [webView _removeObjectForIdentifier:identifier];
493
494     static_cast<WebDocumentLoaderMac*>(loader)->decreaseLoadCount(identifier);
495 }
496
497 void WebFrameLoaderClient::dispatchDidHandleOnloadEvents()
498 {
499     WebView *webView = getWebView(m_webFrame.get());
500     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
501     if (implementations->didHandleOnloadEventsForFrameFunc)
502         CallFrameLoadDelegate(implementations->didHandleOnloadEventsForFrameFunc, webView, @selector(webView:didHandleOnloadEventsForFrame:), m_webFrame.get());
503 }
504
505 void WebFrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad()
506 {
507     WebView *webView = getWebView(m_webFrame.get());
508     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
509     if (implementations->didReceiveServerRedirectForProvisionalLoadForFrameFunc)
510         CallFrameLoadDelegate(implementations->didReceiveServerRedirectForProvisionalLoadForFrameFunc, webView, @selector(webView:didReceiveServerRedirectForProvisionalLoadForFrame:), m_webFrame.get());
511 }
512
513 void WebFrameLoaderClient::dispatchDidCancelClientRedirect()
514 {
515     WebView *webView = getWebView(m_webFrame.get());
516     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
517     if (implementations->didCancelClientRedirectForFrameFunc)
518         CallFrameLoadDelegate(implementations->didCancelClientRedirectForFrameFunc, webView, @selector(webView:didCancelClientRedirectForFrame:), m_webFrame.get());
519 }
520
521 void WebFrameLoaderClient::dispatchWillPerformClientRedirect(const KURL& url, double delay, double fireDate)
522 {
523     WebView *webView = getWebView(m_webFrame.get());
524     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
525     if (implementations->willPerformClientRedirectToURLDelayFireDateForFrameFunc) {
526         NSURL *cocoaURL = url;
527         CallFrameLoadDelegate(implementations->willPerformClientRedirectToURLDelayFireDateForFrameFunc, webView, @selector(webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:), cocoaURL, delay, [NSDate dateWithTimeIntervalSince1970:fireDate], m_webFrame.get());
528     }
529 }
530
531 void WebFrameLoaderClient::dispatchDidChangeLocationWithinPage()
532 {
533     WebView *webView = getWebView(m_webFrame.get());
534     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
535     if (implementations->didChangeLocationWithinPageForFrameFunc)
536         CallFrameLoadDelegate(implementations->didChangeLocationWithinPageForFrameFunc, webView, @selector(webView:didChangeLocationWithinPageForFrame:), m_webFrame.get());
537 }
538
539 void WebFrameLoaderClient::dispatchWillClose()
540 {
541     WebView *webView = getWebView(m_webFrame.get());   
542     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
543     if (implementations->willCloseFrameFunc)
544         CallFrameLoadDelegate(implementations->willCloseFrameFunc, webView, @selector(webView:willCloseFrame:), m_webFrame.get());
545 }
546
547 void WebFrameLoaderClient::dispatchDidReceiveIcon()
548 {
549 #if ENABLE(ICONDATABASE)
550     WebView *webView = getWebView(m_webFrame.get());   
551     ASSERT(m_webFrame == [webView mainFrame]);
552     [webView _dispatchDidReceiveIconFromWebFrame:m_webFrame.get()];
553 #endif
554 }
555
556 void WebFrameLoaderClient::dispatchDidStartProvisionalLoad()
557 {
558     WebView *webView = getWebView(m_webFrame.get());   
559     [webView _didStartProvisionalLoadForFrame:m_webFrame.get()];
560
561     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
562     if (implementations->didStartProvisionalLoadForFrameFunc)
563         CallFrameLoadDelegate(implementations->didStartProvisionalLoadForFrameFunc, webView, @selector(webView:didStartProvisionalLoadForFrame:), m_webFrame.get());
564 }
565
566 void WebFrameLoaderClient::dispatchDidReceiveTitle(const String& title)
567 {
568     WebView *webView = getWebView(m_webFrame.get());   
569     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
570     if (implementations->didReceiveTitleForFrameFunc)
571         CallFrameLoadDelegate(implementations->didReceiveTitleForFrameFunc, webView, @selector(webView:didReceiveTitle:forFrame:), (NSString *)title, m_webFrame.get());
572 }
573
574 void WebFrameLoaderClient::dispatchDidCommitLoad()
575 {
576     // Tell the client we've committed this URL.
577     ASSERT([m_webFrame->_private->webFrameView documentView] != nil || ![getWebView(m_webFrame.get()) _usesDocumentViews]);
578     
579     WebView *webView = getWebView(m_webFrame.get());   
580     [webView _didCommitLoadForFrame:m_webFrame.get()];
581
582     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
583     if (implementations->didCommitLoadForFrameFunc)
584         CallFrameLoadDelegate(implementations->didCommitLoadForFrameFunc, webView, @selector(webView:didCommitLoadForFrame:), m_webFrame.get());
585 }
586
587 void WebFrameLoaderClient::dispatchDidFailProvisionalLoad(const ResourceError& error)
588 {
589     WebView *webView = getWebView(m_webFrame.get());   
590     [webView _didFailProvisionalLoadWithError:error forFrame:m_webFrame.get()];
591
592     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
593     if (implementations->didFailProvisionalLoadWithErrorForFrameFunc)
594         CallFrameLoadDelegate(implementations->didFailProvisionalLoadWithErrorForFrameFunc, webView, @selector(webView:didFailProvisionalLoadWithError:forFrame:), (NSError *)error, m_webFrame.get());
595
596     [m_webFrame->_private->internalLoadDelegate webFrame:m_webFrame.get() didFinishLoadWithError:error];
597 }
598
599 void WebFrameLoaderClient::dispatchDidFailLoad(const ResourceError& error)
600 {
601     WebView *webView = getWebView(m_webFrame.get());   
602     [webView _didFailLoadWithError:error forFrame:m_webFrame.get()];
603
604     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
605     if (implementations->didFailLoadWithErrorForFrameFunc)
606         CallFrameLoadDelegate(implementations->didFailLoadWithErrorForFrameFunc, webView, @selector(webView:didFailLoadWithError:forFrame:), (NSError *)error, m_webFrame.get());
607
608     [m_webFrame->_private->internalLoadDelegate webFrame:m_webFrame.get() didFinishLoadWithError:error];
609 }
610
611 void WebFrameLoaderClient::dispatchDidFinishDocumentLoad()
612 {
613     WebView *webView = getWebView(m_webFrame.get());
614     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
615     if (implementations->didFinishDocumentLoadForFrameFunc)
616         CallFrameLoadDelegate(implementations->didFinishDocumentLoadForFrameFunc, webView, @selector(webView:didFinishDocumentLoadForFrame:), m_webFrame.get());
617 }
618
619 void WebFrameLoaderClient::dispatchDidFinishLoad()
620 {
621     WebView *webView = getWebView(m_webFrame.get());   
622     [webView _didFinishLoadForFrame:m_webFrame.get()];
623
624     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
625     if (implementations->didFinishLoadForFrameFunc)
626         CallFrameLoadDelegate(implementations->didFinishLoadForFrameFunc, webView, @selector(webView:didFinishLoadForFrame:), m_webFrame.get());
627
628     [m_webFrame->_private->internalLoadDelegate webFrame:m_webFrame.get() didFinishLoadWithError:nil];
629 }
630
631 void WebFrameLoaderClient::dispatchDidFirstLayout()
632 {
633     WebView *webView = getWebView(m_webFrame.get());
634     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
635     if (implementations->didFirstLayoutInFrameFunc)
636         CallFrameLoadDelegate(implementations->didFirstLayoutInFrameFunc, webView, @selector(webView:didFirstLayoutInFrame:), m_webFrame.get());
637 }
638
639 void WebFrameLoaderClient::dispatchDidFirstVisuallyNonEmptyLayout()
640 {
641     WebView *webView = getWebView(m_webFrame.get());
642     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
643     if (implementations->didFirstVisuallyNonEmptyLayoutInFrameFunc)
644         CallFrameLoadDelegate(implementations->didFirstVisuallyNonEmptyLayoutInFrameFunc, webView, @selector(webView:didFirstVisuallyNonEmptyLayoutInFrame:), m_webFrame.get());
645 }
646
647 Frame* WebFrameLoaderClient::dispatchCreatePage()
648 {
649     WebView *currentWebView = getWebView(m_webFrame.get());
650     NSDictionary *features = [[NSDictionary alloc] init];
651     WebView *newWebView = [[currentWebView _UIDelegateForwarder] webView:currentWebView 
652                                                 createWebViewWithRequest:nil
653                                                           windowFeatures:features];
654     [features release];
655     
656 #if USE(PLUGIN_HOST_PROCESS)
657     if (newWebView)
658         WebKit::NetscapePluginHostManager::shared().didCreateWindow();
659 #endif
660         
661     return core([newWebView mainFrame]);
662 }
663
664 void WebFrameLoaderClient::dispatchShow()
665 {
666     WebView *webView = getWebView(m_webFrame.get());
667     [[webView _UIDelegateForwarder] webViewShow:webView];
668 }
669
670 void WebFrameLoaderClient::dispatchDecidePolicyForMIMEType(FramePolicyFunction function,
671     const String& MIMEType, const ResourceRequest& request)
672 {
673     WebView *webView = getWebView(m_webFrame.get());
674
675     [[webView _policyDelegateForwarder] webView:webView
676                         decidePolicyForMIMEType:MIMEType
677                                         request:request.nsURLRequest()
678                                           frame:m_webFrame.get()
679                                decisionListener:setUpPolicyListener(function).get()];
680 }
681
682 void WebFrameLoaderClient::dispatchDecidePolicyForNewWindowAction(FramePolicyFunction function,
683     const NavigationAction& action, const ResourceRequest& request, PassRefPtr<FormState> formState, const String& frameName)
684 {
685     WebView *webView = getWebView(m_webFrame.get());
686     [[webView _policyDelegateForwarder] webView:webView
687             decidePolicyForNewWindowAction:actionDictionary(action, formState)
688                                    request:request.nsURLRequest()
689                               newFrameName:frameName
690                           decisionListener:setUpPolicyListener(function).get()];
691 }
692
693 void WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction(FramePolicyFunction function,
694     const NavigationAction& action, const ResourceRequest& request, PassRefPtr<FormState> formState)
695 {
696     WebView *webView = getWebView(m_webFrame.get());
697     [[webView _policyDelegateForwarder] webView:webView
698                 decidePolicyForNavigationAction:actionDictionary(action, formState)
699                                         request:request.nsURLRequest()
700                                           frame:m_webFrame.get()
701                                decisionListener:setUpPolicyListener(function).get()];
702 }
703
704 void WebFrameLoaderClient::cancelPolicyCheck()
705 {
706     [m_policyListener.get() invalidate];
707     m_policyListener = nil;
708     m_policyFunction = 0;
709 }
710
711 void WebFrameLoaderClient::dispatchUnableToImplementPolicy(const ResourceError& error)
712 {
713     WebView *webView = getWebView(m_webFrame.get());
714     [[webView _policyDelegateForwarder] webView:webView unableToImplementPolicyWithError:error frame:m_webFrame.get()];    
715 }
716
717 void WebFrameLoaderClient::dispatchWillSubmitForm(FramePolicyFunction function, PassRefPtr<FormState> formState)
718 {
719     id <WebFormDelegate> formDelegate = [getWebView(m_webFrame.get()) _formDelegate];
720     if (!formDelegate) {
721         (core(m_webFrame.get())->loader()->policyChecker()->*function)(PolicyUse);
722         return;
723     }
724
725     const StringPairVector& textFieldValues = formState->textFieldValues();
726     size_t size = textFieldValues.size();
727     NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] initWithCapacity:size];
728     for (size_t i = 0; i < size; ++i)
729         [dictionary setObject:textFieldValues[i].second forKey:textFieldValues[i].first];
730
731     CallFormDelegate(getWebView(m_webFrame.get()), @selector(frame:sourceFrame:willSubmitForm:withValues:submissionListener:), m_webFrame.get(), kit(formState->sourceFrame()), kit(formState->form()), dictionary, setUpPolicyListener(function).get());
732
733     [dictionary release];
734 }
735
736 void WebFrameLoaderClient::dispatchDidLoadMainResource(DocumentLoader* loader)
737 {
738 }
739
740 void WebFrameLoaderClient::revertToProvisionalState(DocumentLoader* loader)
741 {
742     [dataSource(loader) _revertToProvisionalState];
743 }
744
745 void WebFrameLoaderClient::setMainDocumentError(DocumentLoader* loader, const ResourceError& error)
746 {
747     [dataSource(loader) _setMainDocumentError:error];
748 }
749
750 void WebFrameLoaderClient::willChangeEstimatedProgress()
751 {
752     [getWebView(m_webFrame.get()) _willChangeValueForKey:_WebEstimatedProgressKey];
753 }
754
755 void WebFrameLoaderClient::didChangeEstimatedProgress()
756 {
757     [getWebView(m_webFrame.get()) _didChangeValueForKey:_WebEstimatedProgressKey];
758 }
759
760 void WebFrameLoaderClient::postProgressStartedNotification()
761 {
762     [[NSNotificationCenter defaultCenter] postNotificationName:WebViewProgressStartedNotification object:getWebView(m_webFrame.get())];
763 }
764
765 void WebFrameLoaderClient::postProgressEstimateChangedNotification()
766 {
767     [[NSNotificationCenter defaultCenter] postNotificationName:WebViewProgressEstimateChangedNotification object:getWebView(m_webFrame.get())];
768 }
769
770 void WebFrameLoaderClient::postProgressFinishedNotification()
771 {
772     [[NSNotificationCenter defaultCenter] postNotificationName:WebViewProgressFinishedNotification object:getWebView(m_webFrame.get())];
773 }
774
775 void WebFrameLoaderClient::setMainFrameDocumentReady(bool ready)
776 {
777     [getWebView(m_webFrame.get()) setMainFrameDocumentReady:ready];
778 }
779
780 void WebFrameLoaderClient::startDownload(const ResourceRequest& request)
781 {
782     // FIXME: Should download full request.
783     WebDownload *download = [getWebView(m_webFrame.get()) _downloadURL:request.url()];
784     
785     setOriginalURLForDownload(download, request);
786 }
787
788 void WebFrameLoaderClient::willChangeTitle(DocumentLoader* loader)
789 {
790     // FIXME: Should do this only in main frame case, right?
791     [getWebView(m_webFrame.get()) _willChangeValueForKey:_WebMainFrameTitleKey];
792 }
793
794 void WebFrameLoaderClient::didChangeTitle(DocumentLoader* loader)
795 {
796     // FIXME: Should do this only in main frame case, right?
797     [getWebView(m_webFrame.get()) _didChangeValueForKey:_WebMainFrameTitleKey];
798 }
799
800 void WebFrameLoaderClient::committedLoad(DocumentLoader* loader, const char* data, int length)
801 {
802     NSData *nsData = [[NSData alloc] initWithBytesNoCopy:(void*)data length:length freeWhenDone:NO];
803     [dataSource(loader) _receivedData:nsData];
804     [nsData release];
805 }
806
807 void WebFrameLoaderClient::finishedLoading(DocumentLoader* loader)
808 {
809     [dataSource(loader) _finishedLoading];
810 }
811
812 void WebFrameLoaderClient::updateGlobalHistory()
813 {
814     WebView* view = getWebView(m_webFrame.get());
815     DocumentLoader* loader = core(m_webFrame.get())->loader()->documentLoader();
816
817     if ([view historyDelegate]) {
818         WebHistoryDelegateImplementationCache* implementations = WebViewGetHistoryDelegateImplementations(view);
819         if (implementations->navigatedFunc) {
820             WebNavigationData *data = [[WebNavigationData alloc] initWithURLString:loader->urlForHistory()
821                                                                              title:loader->title()
822                                                                    originalRequest:loader->originalRequestCopy().nsURLRequest()
823                                                                           response:loader->response().nsURLResponse()
824                                                                  hasSubstituteData:loader->substituteData().isValid()
825                                                               clientRedirectSource:loader->clientRedirectSourceForHistory()];
826
827             CallHistoryDelegate(implementations->navigatedFunc, view, @selector(webView:didNavigateWithNavigationData:inFrame:), data, m_webFrame.get());
828             [data release];
829         }
830     
831         return;
832     }
833
834     [[WebHistory optionalSharedHistory] _visitedURL:loader->urlForHistory() 
835                                           withTitle:loader->title()
836                                              method:loader->originalRequestCopy().httpMethod()
837                                          wasFailure:loader->urlForHistoryReflectsFailure()
838                                  increaseVisitCount:!loader->clientRedirectSourceForHistory()]; // Do not increase visit count due to navigations that were not initiated by the user directly, avoiding growth from programmatic reloads.
839 }
840
841 void WebFrameLoaderClient::updateGlobalHistoryRedirectLinks()
842 {
843     WebView* view = getWebView(m_webFrame.get());
844     WebHistoryDelegateImplementationCache* implementations = [view historyDelegate] ? WebViewGetHistoryDelegateImplementations(view) : 0;
845     
846     DocumentLoader* loader = core(m_webFrame.get())->loader()->documentLoader();
847     ASSERT(loader->unreachableURL().isEmpty());
848
849     if (!loader->clientRedirectSourceForHistory().isNull()) {
850         if (implementations) {
851             if (implementations->clientRedirectFunc) {
852                 CallHistoryDelegate(implementations->clientRedirectFunc, view, @selector(webView:didPerformClientRedirectFromURL:toURL:inFrame:), 
853                     loader->clientRedirectSourceForHistory(), loader->clientRedirectDestinationForHistory(), m_webFrame.get());
854             }
855         } else if (WebHistoryItem *item = [[WebHistory optionalSharedHistory] _itemForURLString:loader->clientRedirectSourceForHistory()])
856             core(item)->addRedirectURL(loader->clientRedirectDestinationForHistory());
857     }
858
859     if (!loader->serverRedirectSourceForHistory().isNull()) {
860         if (implementations) {
861             if (implementations->serverRedirectFunc) {
862                 CallHistoryDelegate(implementations->serverRedirectFunc, view, @selector(webView:didPerformServerRedirectFromURL:toURL:inFrame:), 
863                     loader->serverRedirectSourceForHistory(), loader->serverRedirectDestinationForHistory(), m_webFrame.get());
864             }
865         } else if (WebHistoryItem *item = [[WebHistory optionalSharedHistory] _itemForURLString:loader->serverRedirectSourceForHistory()])
866             core(item)->addRedirectURL(loader->serverRedirectDestinationForHistory());
867     }
868 }
869
870 bool WebFrameLoaderClient::shouldGoToHistoryItem(HistoryItem* item) const
871 {
872     WebView* view = getWebView(m_webFrame.get());
873     WebHistoryItem *webItem = kit(item);
874     
875     return [[view _policyDelegateForwarder] webView:view shouldGoToHistoryItem:webItem];
876 }
877
878 void WebFrameLoaderClient::didDisplayInsecureContent()
879 {
880     WebView *webView = getWebView(m_webFrame.get());   
881     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
882     if (implementations->didDisplayInsecureContentFunc)
883         CallFrameLoadDelegate(implementations->didDisplayInsecureContentFunc, webView, @selector(webViewDidDisplayInsecureContent:));
884 }
885
886 void WebFrameLoaderClient::didRunInsecureContent(SecurityOrigin* origin)
887 {
888     RetainPtr<WebSecurityOrigin> webSecurityOrigin(AdoptNS, [[WebSecurityOrigin alloc] _initWithWebCoreSecurityOrigin:origin]);
889
890     WebView *webView = getWebView(m_webFrame.get());   
891     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
892     if (implementations->didRunInsecureContentFunc)
893         CallFrameLoadDelegate(implementations->didRunInsecureContentFunc, webView, @selector(webView:didRunInsecureContent:), webSecurityOrigin.get());
894 }
895
896 ResourceError WebFrameLoaderClient::cancelledError(const ResourceRequest& request)
897 {
898     return [NSError _webKitErrorWithDomain:NSURLErrorDomain code:NSURLErrorCancelled URL:request.url()];
899 }
900     
901 ResourceError WebFrameLoaderClient::blockedError(const ResourceRequest& request)
902 {
903     return [NSError _webKitErrorWithDomain:WebKitErrorDomain code:WebKitErrorCannotUseRestrictedPort URL:request.url()];
904 }
905
906 ResourceError WebFrameLoaderClient::cannotShowURLError(const ResourceRequest& request)
907 {
908     return [NSError _webKitErrorWithDomain:WebKitErrorDomain code:WebKitErrorCannotShowURL URL:request.url()];
909 }
910
911 ResourceError WebFrameLoaderClient::interruptForPolicyChangeError(const ResourceRequest& request)
912 {
913     return [NSError _webKitErrorWithDomain:WebKitErrorDomain code:WebKitErrorFrameLoadInterruptedByPolicyChange URL:request.url()];
914 }
915
916 ResourceError WebFrameLoaderClient::cannotShowMIMETypeError(const ResourceResponse& response)
917 {
918     return [NSError _webKitErrorWithDomain:NSURLErrorDomain code:WebKitErrorCannotShowMIMEType URL:response.url()];
919 }
920
921 ResourceError WebFrameLoaderClient::fileDoesNotExistError(const ResourceResponse& response)
922 {
923     return [NSError _webKitErrorWithDomain:NSURLErrorDomain code:NSURLErrorFileDoesNotExist URL:response.url()];    
924 }
925
926 ResourceError WebFrameLoaderClient::pluginWillHandleLoadError(const ResourceResponse& response)
927 {
928     NSError *error = [[NSError alloc] _initWithPluginErrorCode:WebKitErrorPlugInWillHandleLoad
929                                                     contentURL:response.url()
930                                                  pluginPageURL:nil
931                                                     pluginName:nil
932                                                       MIMEType:response.mimeType()];
933     return [error autorelease];
934 }
935
936 bool WebFrameLoaderClient::shouldFallBack(const ResourceError& error)
937 {
938     // FIXME: Needs to check domain.
939     // FIXME: WebKitErrorPlugInWillHandleLoad is a workaround for the cancel we do to prevent
940     // loading plugin content twice.  See <rdar://problem/4258008>
941     return error.errorCode() != NSURLErrorCancelled && error.errorCode() != WebKitErrorPlugInWillHandleLoad;
942 }
943
944 bool WebFrameLoaderClient::canHandleRequest(const ResourceRequest& request) const
945 {
946     Frame* frame = core(m_webFrame.get());
947     Page* page = frame->page();
948     BOOL forMainFrame = page && page->mainFrame() == frame;
949     return [WebView _canHandleRequest:request.nsURLRequest() forMainFrame:forMainFrame];
950 }
951
952 bool WebFrameLoaderClient::canShowMIMEType(const String& MIMEType) const
953 {
954     return [WebView canShowMIMEType:MIMEType];
955 }
956
957 bool WebFrameLoaderClient::representationExistsForURLScheme(const String& URLScheme) const
958 {
959     return [WebView _representationExistsForURLScheme:URLScheme];
960 }
961
962 String WebFrameLoaderClient::generatedMIMETypeForURLScheme(const String& URLScheme) const
963 {
964     return [WebView _generatedMIMETypeForURLScheme:URLScheme];
965 }
966
967 void WebFrameLoaderClient::frameLoadCompleted()
968 {
969     // Note: Can be called multiple times.
970
971     // See WebFrameLoaderClient::provisionalLoadStarted.
972     if ([getWebView(m_webFrame.get()) drawsBackground])
973         [[m_webFrame->_private->webFrameView _scrollView] setDrawsBackground:YES];
974 }
975
976 void WebFrameLoaderClient::saveViewStateToItem(HistoryItem* item)
977 {
978     if (!item)
979         return;
980     
981     NSView <WebDocumentView> *docView = [m_webFrame->_private->webFrameView documentView];
982
983     // we might already be detached when this is called from detachFromParent, in which
984     // case we don't want to override real data earlier gathered with (0,0)
985     if ([docView superview] && [docView conformsToProtocol:@protocol(_WebDocumentViewState)])
986         item->setViewState([(id <_WebDocumentViewState>)docView viewState]);
987 }
988
989 void WebFrameLoaderClient::restoreViewState()
990 {
991     HistoryItem* currentItem = core(m_webFrame.get())->loader()->currentHistoryItem();
992     ASSERT(currentItem);
993
994     // FIXME: As the ASSERT attests, it seems we should always have a currentItem here.
995     // One counterexample is <rdar://problem/4917290>
996     // For now, to cover this issue in release builds, there is no technical harm to returning
997     // early and from a user standpoint - as in the above radar - the previous page load failed 
998     // so there *is* no scroll state to restore!
999     if (!currentItem)
1000         return;
1001     
1002     NSView <WebDocumentView> *docView = [m_webFrame->_private->webFrameView documentView];
1003     if ([docView conformsToProtocol:@protocol(_WebDocumentViewState)]) {        
1004         id state = currentItem->viewState();
1005         if (state) {
1006             [(id <_WebDocumentViewState>)docView setViewState:state];
1007         }
1008     }
1009 }
1010
1011 void WebFrameLoaderClient::provisionalLoadStarted()
1012 {    
1013     // Tell the scroll view not to draw a background so we can leave the contents of
1014     // the old page showing during the beginning of the loading process.
1015
1016     // This will stay set to NO until:
1017     //    1) The load gets far enough along: WebFrameLoader::frameLoadCompleted.
1018     //    2) The window is resized: -[WebFrameView setFrameSize:].
1019     // or 3) The view is moved out of the window: -[WebFrameView viewDidMoveToWindow].
1020     // Please keep the comments in these four functions in agreement with each other.
1021
1022     [[m_webFrame->_private->webFrameView _scrollView] setDrawsBackground:NO];
1023 }
1024
1025 void WebFrameLoaderClient::didFinishLoad()
1026 {
1027     [m_webFrame->_private->internalLoadDelegate webFrame:m_webFrame.get() didFinishLoadWithError:nil];    
1028 }
1029
1030 void WebFrameLoaderClient::prepareForDataSourceReplacement()
1031 {
1032     if (![m_webFrame.get() _dataSource]) {
1033         ASSERT(!core(m_webFrame.get())->tree()->childCount());
1034         return;
1035     }
1036     
1037     // Make sure that any work that is triggered by resigning first reponder can get done.
1038     // The main example where this came up is the textDidEndEditing that is sent to the
1039     // FormsDelegate (3223413). We need to do this before _detachChildren, since that will
1040     // remove the views as a side-effect of freeing the frame, at which point we can't
1041     // post the FormDelegate messages.
1042     //
1043     // Note that this can also take FirstResponder away from a child of our frameView that
1044     // is not in a child frame's view.  This is OK because we are in the process
1045     // of loading new content, which will blow away all editors in this top frame, and if
1046     // a non-editor is firstReponder it will not be affected by endEditingFor:.
1047     // Potentially one day someone could write a DocView whose editors were not all
1048     // replaced by loading new content, but that does not apply currently.
1049     NSView *frameView = m_webFrame->_private->webFrameView;
1050     NSWindow *window = [frameView window];
1051     NSResponder *firstResp = [window firstResponder];
1052     if ([firstResp isKindOfClass:[NSView class]] && [(NSView *)firstResp isDescendantOf:frameView])
1053         [window endEditingFor:firstResp];
1054 }
1055
1056 PassRefPtr<DocumentLoader> WebFrameLoaderClient::createDocumentLoader(const ResourceRequest& request, const SubstituteData& substituteData)
1057 {
1058     RefPtr<WebDocumentLoaderMac> loader = WebDocumentLoaderMac::create(request, substituteData);
1059
1060     WebDataSource *dataSource = [[WebDataSource alloc] _initWithDocumentLoader:loader.get()];
1061     loader->setDataSource(dataSource, getWebView(m_webFrame.get()));
1062     [dataSource release];
1063
1064     return loader.release();
1065 }
1066
1067 void WebFrameLoaderClient::setTitle(const String& title, const KURL& url)
1068 {
1069     WebView* view = getWebView(m_webFrame.get());
1070     
1071     if ([view historyDelegate]) {
1072         WebHistoryDelegateImplementationCache* implementations = WebViewGetHistoryDelegateImplementations(view);
1073         if (!implementations->setTitleFunc)
1074             return;
1075             
1076         CallHistoryDelegate(implementations->setTitleFunc, view, @selector(webView:updateHistoryTitle:forURL:), (NSString *)title, (NSString *)url);
1077         return;
1078     }
1079     
1080     NSURL* nsURL = url;
1081     nsURL = [nsURL _webkit_canonicalize];
1082     if(!nsURL)
1083         return;
1084     NSString *titleNSString = title;
1085        
1086     [[[WebHistory optionalSharedHistory] itemForURL:nsURL] setTitle:titleNSString];
1087 }
1088
1089 void WebFrameLoaderClient::savePlatformDataToCachedFrame(CachedFrame* cachedFrame)
1090 {
1091     WebCachedFramePlatformData* webPlatformData = new WebCachedFramePlatformData([m_webFrame->_private->webFrameView documentView]);
1092     cachedFrame->setCachedFramePlatformData(webPlatformData);
1093 }
1094
1095 void WebFrameLoaderClient::transitionToCommittedFromCachedFrame(CachedFrame* cachedFrame)
1096 {
1097     WebCachedFramePlatformData* platformData = reinterpret_cast<WebCachedFramePlatformData*>(cachedFrame->cachedFramePlatformData());
1098     NSView <WebDocumentView> *cachedView = platformData->webDocumentView();
1099     ASSERT(cachedView != nil);
1100     ASSERT(cachedFrame->documentLoader());
1101     [cachedView setDataSource:dataSource(cachedFrame->documentLoader())];
1102     
1103     // clean up webkit plugin instances before WebHTMLView gets freed.
1104     WebView *webView = getWebView(m_webFrame.get());
1105     [webView removePluginInstanceViewsFor:(m_webFrame.get())];
1106     
1107     [m_webFrame->_private->webFrameView _setDocumentView:cachedView];
1108 }
1109
1110 void WebFrameLoaderClient::transitionToCommittedForNewPage()
1111 {
1112     WebView *webView = getWebView(m_webFrame.get());
1113     WebDataSource *dataSource = [m_webFrame.get() _dataSource];
1114     bool usesDocumentViews = [webView _usesDocumentViews];
1115
1116     if (usesDocumentViews) {
1117         // FIXME (Viewless): I assume we want the equivalent of this optimization for viewless mode too.
1118         bool willProduceHTMLView = [[WebFrameView class] _viewClassForMIMEType:[dataSource _responseMIMEType]] == [WebHTMLView class];
1119         bool canSkipCreation = core(m_webFrame.get())->loader()->committingFirstRealLoad() && willProduceHTMLView;
1120         if (canSkipCreation) {
1121             [[m_webFrame->_private->webFrameView documentView] setDataSource:dataSource];
1122             return;
1123         }
1124
1125         // Don't suppress scrollbars before the view creation if we're making the view for a non-HTML view.
1126         if (!willProduceHTMLView)
1127             [[m_webFrame->_private->webFrameView _scrollView] setScrollBarsSuppressed:NO repaintOnUnsuppress:NO];
1128     }
1129     
1130     // clean up webkit plugin instances before WebHTMLView gets freed.
1131     [webView removePluginInstanceViewsFor:(m_webFrame.get())];
1132     
1133     NSView <WebDocumentView> *documentView = nil;
1134     if (usesDocumentViews) {
1135         documentView = [m_webFrame->_private->webFrameView _makeDocumentViewForDataSource:dataSource];
1136         if (!documentView)
1137             return;
1138     }
1139
1140     // FIXME: Could we skip some of this work for a top-level view that is not a WebHTMLView?
1141
1142     // If we own the view, delete the old one - otherwise the render m_frame will take care of deleting the view.
1143     Frame* coreFrame = core(m_webFrame.get());
1144     Page* page = coreFrame->page();
1145     bool isMainFrame = coreFrame == page->mainFrame();
1146     if (isMainFrame && coreFrame->view())
1147         coreFrame->view()->setParentVisible(false);
1148     coreFrame->setView(0);
1149     RefPtr<FrameView> coreView;
1150     if (usesDocumentViews)
1151         coreView = FrameView::create(coreFrame);
1152     else
1153         coreView = FrameView::create(coreFrame, IntSize([webView bounds].size));
1154     coreFrame->setView(coreView);
1155
1156     [m_webFrame.get() _updateBackgroundAndUpdatesWhileOffscreen];
1157
1158     if (usesDocumentViews)
1159         [m_webFrame->_private->webFrameView _install];
1160
1161     if (isMainFrame)
1162         coreView->setParentVisible(true);
1163
1164     if (usesDocumentViews) {
1165         // Call setDataSource on the document view after it has been placed in the view hierarchy.
1166         // This what we for the top-level view, so should do this for views in subframes as well.
1167         [documentView setDataSource:dataSource];
1168
1169         // The following is a no-op for WebHTMLRepresentation, but for custom document types
1170         // like the ones that Safari uses for bookmarks it is the only way the DocumentLoader
1171         // will get the proper title.
1172         if (DocumentLoader* documentLoader = [dataSource _documentLoader])
1173             documentLoader->setTitle([dataSource pageTitle]);
1174     }
1175
1176     if (HTMLFrameOwnerElement* owner = coreFrame->ownerElement())
1177         coreFrame->view()->setCanHaveScrollbars(owner->scrollingMode() != ScrollbarAlwaysOff);
1178         
1179     // If the document view implicitly became first responder, make sure to set the focused frame properly.
1180     if (usesDocumentViews && [[documentView window] firstResponder] == documentView) {
1181         page->focusController()->setFocusedFrame(coreFrame);
1182         page->focusController()->setFocused(true);
1183     }
1184 }
1185
1186 RetainPtr<WebFramePolicyListener> WebFrameLoaderClient::setUpPolicyListener(FramePolicyFunction function)
1187 {
1188     // FIXME: <rdar://5634381> We need to support multiple active policy listeners.
1189
1190     [m_policyListener.get() invalidate];
1191
1192     WebFramePolicyListener *listener = [[WebFramePolicyListener alloc] initWithWebCoreFrame:core(m_webFrame.get())];
1193     m_policyListener = listener;
1194     [listener release];
1195     m_policyFunction = function;
1196
1197     return listener;
1198 }
1199
1200 void WebFrameLoaderClient::receivedPolicyDecison(PolicyAction action)
1201 {
1202     ASSERT(m_policyListener);
1203     ASSERT(m_policyFunction);
1204
1205     FramePolicyFunction function = m_policyFunction;
1206
1207     m_policyListener = nil;
1208     m_policyFunction = 0;
1209
1210     (core(m_webFrame.get())->loader()->policyChecker()->*function)(action);
1211 }
1212
1213 String WebFrameLoaderClient::userAgent(const KURL& url)
1214 {
1215     WebView *webView = getWebView(m_webFrame.get());
1216     ASSERT(webView);
1217
1218     // We should never get here with nil for the WebView unless there is a bug somewhere else.
1219     // But if we do, it's better to return the empty string than just crashing on the spot.
1220     // Most other call sites are tolerant of nil because of Objective-C behavior, but this one
1221     // is not because the return value of _userAgentForURL is a const KURL&.
1222     if (!webView)
1223         return String("");
1224
1225     return [webView _userAgentForURL:url];
1226 }
1227
1228 static const MouseEvent* findMouseEvent(const Event* event)
1229 {
1230     for (const Event* e = event; e; e = e->underlyingEvent())
1231         if (e->isMouseEvent())
1232             return static_cast<const MouseEvent*>(e);
1233     return 0;
1234 }
1235
1236 NSDictionary *WebFrameLoaderClient::actionDictionary(const NavigationAction& action, PassRefPtr<FormState> formState) const
1237 {
1238     unsigned modifierFlags = 0;
1239     const Event* event = action.event();
1240     if (const UIEventWithKeyState* keyStateEvent = findEventWithKeyState(const_cast<Event*>(event))) {
1241         if (keyStateEvent->ctrlKey())
1242             modifierFlags |= NSControlKeyMask;
1243         if (keyStateEvent->altKey())
1244             modifierFlags |= NSAlternateKeyMask;
1245         if (keyStateEvent->shiftKey())
1246             modifierFlags |= NSShiftKeyMask;
1247         if (keyStateEvent->metaKey())
1248             modifierFlags |= NSCommandKeyMask;
1249     }
1250
1251     NSURL *originalURL = action.url();
1252
1253     NSMutableDictionary *result = [NSMutableDictionary dictionaryWithObjectsAndKeys:
1254         [NSNumber numberWithInt:action.type()], WebActionNavigationTypeKey,
1255         [NSNumber numberWithInt:modifierFlags], WebActionModifierFlagsKey,
1256         originalURL, WebActionOriginalURLKey,
1257         nil];
1258
1259     if (const MouseEvent* mouseEvent = findMouseEvent(event)) {
1260         WebElementDictionary *element = [[WebElementDictionary alloc]
1261             initWithHitTestResult:core(m_webFrame.get())->eventHandler()->hitTestResultAtPoint(mouseEvent->absoluteLocation(), false)];
1262         [result setObject:element forKey:WebActionElementKey];
1263         [element release];
1264
1265         [result setObject:[NSNumber numberWithInt:mouseEvent->button()] forKey:WebActionButtonKey];
1266     }
1267
1268     if (formState) {
1269         ASSERT(formState->form());
1270         [result setObject:kit(formState->form()) forKey:WebActionFormKey];
1271     }
1272
1273     return result;
1274 }
1275
1276 bool WebFrameLoaderClient::canCachePage() const
1277 {
1278     // We can only cache HTML pages right now
1279     return [[[m_webFrame.get() _dataSource] representation] isKindOfClass:[WebHTMLRepresentation class]];
1280 }
1281
1282 PassRefPtr<Frame> WebFrameLoaderClient::createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement,
1283     const String& referrer, bool allowsScrolling, int marginWidth, int marginHeight)
1284 {
1285     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1286     
1287     ASSERT(m_webFrame);
1288     
1289     WebFrameView *childView = [getWebView(m_webFrame.get()) _usesDocumentViews] ? [[WebFrameView alloc] init] : nil;
1290     
1291     RefPtr<Frame> result = [WebFrame _createSubframeWithOwnerElement:ownerElement frameName:name frameView:childView];
1292     [childView release];
1293
1294     WebFrame *newFrame = kit(result.get());
1295
1296     if ([newFrame _dataSource])
1297         [[newFrame _dataSource] _documentLoader]->setOverrideEncoding([[m_webFrame.get() _dataSource] _documentLoader]->overrideEncoding());  
1298
1299     // The creation of the frame may have run arbitrary JavaScript that removed it from the page already.
1300     if (!result->page())
1301         return 0;
1302  
1303     core(m_webFrame.get())->loader()->loadURLIntoChildFrame(url, referrer, result.get());
1304
1305     // The frame's onload handler may have removed it from the document.
1306     if (!result->tree()->parent())
1307         return 0;
1308
1309     return result.release();
1310
1311     END_BLOCK_OBJC_EXCEPTIONS;
1312
1313     return 0;
1314 }
1315
1316 ObjectContentType WebFrameLoaderClient::objectContentType(const KURL& url, const String& mimeType)
1317 {
1318     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1319
1320     // This is a quirk that ensures Tiger Mail's WebKit plug-in will load during layout
1321     // and not attach time. (5520541)
1322     static BOOL isTigerMail = WKAppVersionCheckLessThan(@"com.apple.mail", -1, 3.0);
1323     if (isTigerMail && mimeType == "application/x-apple-msg-attachment")
1324         return ObjectContentNetscapePlugin;
1325
1326     String type = mimeType;
1327
1328     if (type.isEmpty()) {
1329         // Try to guess the MIME type based off the extension.
1330         NSURL *URL = url;
1331         NSString *extension = [[URL path] pathExtension];
1332         if ([extension length] > 0) {
1333             type = WKGetMIMETypeForExtension(extension);
1334             if (type.isEmpty()) {
1335                 // If no MIME type is specified, use a plug-in if we have one that can handle the extension.
1336                 if (WebBasePluginPackage *package = [getWebView(m_webFrame.get()) _pluginForExtension:extension]) {
1337                     if ([package isKindOfClass:[WebPluginPackage class]]) 
1338                         return ObjectContentOtherPlugin;
1339 #if ENABLE(NETSCAPE_PLUGIN_API)
1340                     else {
1341                         ASSERT([package isKindOfClass:[WebNetscapePluginPackage class]]);
1342                         return ObjectContentNetscapePlugin;
1343                     }
1344 #endif
1345                 }
1346             }
1347         }
1348     }
1349
1350     if (type.isEmpty())
1351         return ObjectContentFrame; // Go ahead and hope that we can display the content.
1352
1353     if (MIMETypeRegistry::isSupportedImageMIMEType(type))
1354         return ObjectContentImage;
1355
1356     WebBasePluginPackage *package = [getWebView(m_webFrame.get()) _pluginForMIMEType:type];
1357     if (package) {
1358 #if ENABLE(NETSCAPE_PLUGIN_API)
1359         if ([package isKindOfClass:[WebNetscapePluginPackage class]])
1360             return ObjectContentNetscapePlugin;
1361 #endif
1362         ASSERT([package isKindOfClass:[WebPluginPackage class]]);
1363         return ObjectContentOtherPlugin;
1364     }
1365
1366     if ([WebFrameView _viewClassForMIMEType:type])
1367         return ObjectContentFrame;
1368     
1369     return ObjectContentNone;
1370
1371     END_BLOCK_OBJC_EXCEPTIONS;
1372
1373     return ObjectContentNone;
1374 }
1375
1376 static NSMutableArray* kit(const Vector<String>& vector)
1377 {
1378     unsigned len = vector.size();
1379     NSMutableArray* array = [NSMutableArray arrayWithCapacity:len];
1380     for (unsigned x = 0; x < len; x++)
1381         [array addObject:vector[x]];
1382     return array;
1383 }
1384
1385 static String parameterValue(const Vector<String>& paramNames, const Vector<String>& paramValues, const String& name)
1386 {
1387     size_t size = paramNames.size();
1388     ASSERT(size == paramValues.size());
1389     for (size_t i = 0; i < size; ++i) {
1390         if (equalIgnoringCase(paramNames[i], name))
1391             return paramValues[i];
1392     }
1393     return String();
1394 }
1395
1396 static NSView *pluginView(WebFrame *frame, WebPluginPackage *pluginPackage,
1397     NSArray *attributeNames, NSArray *attributeValues, NSURL *baseURL,
1398     DOMElement *element, BOOL loadManually)
1399 {
1400     WebHTMLView *docView = (WebHTMLView *)[[frame frameView] documentView];
1401     ASSERT([docView isKindOfClass:[WebHTMLView class]]);
1402         
1403     WebPluginController *pluginController = [docView _pluginController];
1404     
1405     // Store attributes in a dictionary so they can be passed to WebPlugins.
1406     NSMutableDictionary *attributes = [[NSMutableDictionary alloc] initWithObjects:attributeValues forKeys:attributeNames];
1407     
1408     [pluginPackage load];
1409     Class viewFactory = [pluginPackage viewFactory];
1410     
1411     NSView *view = nil;
1412     NSDictionary *arguments = nil;
1413     
1414     if ([viewFactory respondsToSelector:@selector(plugInViewWithArguments:)]) {
1415         arguments = [NSDictionary dictionaryWithObjectsAndKeys:
1416             baseURL, WebPlugInBaseURLKey,
1417             attributes, WebPlugInAttributesKey,
1418             pluginController, WebPlugInContainerKey,
1419             [NSNumber numberWithInt:loadManually ? WebPlugInModeFull : WebPlugInModeEmbed], WebPlugInModeKey,
1420             [NSNumber numberWithBool:!loadManually], WebPlugInShouldLoadMainResourceKey,
1421             element, WebPlugInContainingElementKey,
1422             nil];
1423         LOG(Plugins, "arguments:\n%@", arguments);
1424     } else if ([viewFactory respondsToSelector:@selector(pluginViewWithArguments:)]) {
1425         arguments = [NSDictionary dictionaryWithObjectsAndKeys:
1426             baseURL, WebPluginBaseURLKey,
1427             attributes, WebPluginAttributesKey,
1428             pluginController, WebPluginContainerKey,
1429             element, WebPlugInContainingElementKey,
1430             nil];
1431         LOG(Plugins, "arguments:\n%@", arguments);
1432     }
1433
1434     view = [WebPluginController plugInViewWithArguments:arguments fromPluginPackage:pluginPackage];
1435     [attributes release];
1436     return view;
1437 }
1438
1439 class PluginWidget : public Widget {
1440 public:
1441     PluginWidget(NSView *view = 0)
1442         : Widget(view)
1443     {
1444     }
1445     
1446     virtual void invalidateRect(const IntRect& rect)
1447     {
1448         [platformWidget() setNeedsDisplayInRect:rect];
1449     }
1450 };
1451
1452 #if ENABLE(NETSCAPE_PLUGIN_API)
1453
1454 class NetscapePluginWidget : public PluginWidget {
1455 public:
1456     NetscapePluginWidget(WebBaseNetscapePluginView *view)
1457         : PluginWidget(view)
1458     {
1459     }
1460     
1461     virtual void handleEvent(Event*)
1462     {
1463         Frame* frame = Frame::frameForWidget(this);
1464         if (!frame)
1465             return;
1466         
1467         NSEvent* event = frame->eventHandler()->currentNSEvent();
1468         if ([event type] == NSMouseMoved)
1469             [(WebBaseNetscapePluginView *)platformWidget() handleMouseMoved:event];
1470     }
1471     
1472 };
1473
1474 #endif // ENABLE(NETSCAPE_PLUGIN_API)
1475
1476 #if USE(PLUGIN_HOST_PROCESS)
1477 #define NETSCAPE_PLUGIN_VIEW WebHostedNetscapePluginView
1478 #else
1479 #define NETSCAPE_PLUGIN_VIEW WebNetscapePluginView
1480 #endif
1481
1482 PassRefPtr<Widget> WebFrameLoaderClient::createPlugin(const IntSize& size, HTMLPlugInElement* element, const KURL& url,
1483     const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually)
1484 {
1485     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1486
1487     ASSERT(paramNames.size() == paramValues.size());
1488
1489     int errorCode = 0;
1490
1491     WebView *webView = getWebView(m_webFrame.get());
1492     SEL selector = @selector(webView:plugInViewWithArguments:);
1493     NSURL *URL = url;
1494
1495     if ([[webView UIDelegate] respondsToSelector:selector]) {
1496         NSMutableDictionary *attributes = [[NSMutableDictionary alloc] initWithObjects:kit(paramValues) forKeys:kit(paramNames)];
1497         NSDictionary *arguments = [[NSDictionary alloc] initWithObjectsAndKeys:
1498             attributes, WebPlugInAttributesKey,
1499             [NSNumber numberWithInt:loadManually ? WebPlugInModeFull : WebPlugInModeEmbed], WebPlugInModeKey,
1500             [NSNumber numberWithBool:!loadManually], WebPlugInShouldLoadMainResourceKey,
1501             kit(element), WebPlugInContainingElementKey,
1502             URL, WebPlugInBaseURLKey, // URL might be nil, so add it last
1503             nil];
1504
1505         NSView *view = CallUIDelegate(webView, selector, arguments);
1506
1507         [attributes release];
1508         [arguments release];
1509
1510         if (view)
1511             return adoptRef(new PluginWidget(view));
1512     }
1513
1514     NSString *MIMEType;
1515     WebBasePluginPackage *pluginPackage;
1516     if (mimeType.isEmpty()) {
1517         MIMEType = nil;
1518         pluginPackage = nil;
1519     } else {
1520         MIMEType = mimeType;
1521         pluginPackage = [webView _pluginForMIMEType:mimeType];
1522     }
1523     
1524     NSString *extension = [[URL path] pathExtension];
1525 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
1526     // don't allow proxy plug-in selection by file extension
1527     if (element->hasTagName(videoTag) || element->hasTagName(audioTag))
1528         extension = @"";
1529 #endif
1530
1531     if (!pluginPackage && [extension length] != 0) {
1532         pluginPackage = [webView _pluginForExtension:extension];
1533         if (pluginPackage) {
1534             NSString *newMIMEType = [pluginPackage MIMETypeForExtension:extension];
1535             if ([newMIMEType length] != 0)
1536                 MIMEType = newMIMEType;
1537         }
1538     }
1539
1540     NSView *view = nil;
1541
1542     Document* document = core(m_webFrame.get())->document();
1543     NSURL *baseURL = document->baseURL();
1544     if (pluginPackage) {
1545         if ([pluginPackage isKindOfClass:[WebPluginPackage class]])
1546             view = pluginView(m_webFrame.get(), (WebPluginPackage *)pluginPackage, kit(paramNames), kit(paramValues), baseURL, kit(element), loadManually);
1547             
1548 #if ENABLE(NETSCAPE_PLUGIN_API)
1549         else if ([pluginPackage isKindOfClass:[WebNetscapePluginPackage class]]) {
1550             WebBaseNetscapePluginView *pluginView = [[[NETSCAPE_PLUGIN_VIEW alloc]
1551                 initWithFrame:NSMakeRect(0, 0, size.width(), size.height())
1552                 pluginPackage:(WebNetscapePluginPackage *)pluginPackage
1553                 URL:URL
1554                 baseURL:baseURL
1555                 MIMEType:MIMEType
1556                 attributeKeys:kit(paramNames)
1557                 attributeValues:kit(paramValues)
1558                 loadManually:loadManually
1559                 element:element] autorelease];
1560             
1561             return adoptRef(new NetscapePluginWidget(pluginView));
1562         } 
1563 #endif
1564     } else
1565         errorCode = WebKitErrorCannotFindPlugIn;
1566
1567     if (!errorCode && !view)
1568         errorCode = WebKitErrorCannotLoadPlugIn;
1569
1570     if (errorCode) {
1571         KURL pluginPageURL = document->completeURL(deprecatedParseURL(parameterValue(paramNames, paramValues, "pluginspage")));
1572         if (!pluginPageURL.protocolInHTTPFamily())
1573             pluginPageURL = KURL();
1574         NSError *error = [[NSError alloc] _initWithPluginErrorCode:errorCode
1575             contentURL:URL pluginPageURL:pluginPageURL pluginName:[pluginPackage name] MIMEType:MIMEType];
1576         WebNullPluginView *nullView = [[[WebNullPluginView alloc] initWithFrame:NSMakeRect(0, 0, size.width(), size.height())
1577             error:error DOMElement:kit(element)] autorelease];
1578         view = nullView;
1579         [error release];
1580     }
1581     
1582     ASSERT(view);
1583     return adoptRef(new PluginWidget(view));
1584
1585     END_BLOCK_OBJC_EXCEPTIONS;
1586
1587     return 0;
1588 }
1589
1590 void WebFrameLoaderClient::redirectDataToPlugin(Widget* pluginWidget)
1591 {
1592     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1593
1594     WebHTMLRepresentation *representation = (WebHTMLRepresentation *)[[m_webFrame.get() _dataSource] representation];
1595
1596     NSView *pluginView = pluginWidget->platformWidget();
1597
1598 #if ENABLE(NETSCAPE_PLUGIN_API)
1599     if ([pluginView isKindOfClass:[NETSCAPE_PLUGIN_VIEW class]])
1600         [representation _redirectDataToManualLoader:(NETSCAPE_PLUGIN_VIEW *)pluginView forPluginView:pluginView];
1601     else {
1602 #else
1603     {
1604 #endif
1605         WebHTMLView *documentView = (WebHTMLView *)[[m_webFrame.get() frameView] documentView];
1606         ASSERT([documentView isKindOfClass:[WebHTMLView class]]);
1607         [representation _redirectDataToManualLoader:[documentView _pluginController] forPluginView:pluginView];
1608     }
1609
1610     END_BLOCK_OBJC_EXCEPTIONS;
1611 }
1612     
1613 PassRefPtr<Widget> WebFrameLoaderClient::createJavaAppletWidget(const IntSize& size, HTMLAppletElement* element, const KURL& baseURL, 
1614     const Vector<String>& paramNames, const Vector<String>& paramValues)
1615 {
1616 #if ENABLE(MAC_JAVA_BRIDGE)
1617     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1618
1619     NSView *view = nil;
1620
1621     NSString *MIMEType = @"application/x-java-applet";
1622     
1623     WebView *webView = getWebView(m_webFrame.get());
1624
1625     WebBasePluginPackage *pluginPackage = [webView _pluginForMIMEType:MIMEType];
1626
1627     if (pluginPackage) {
1628         if ([pluginPackage isKindOfClass:[WebPluginPackage class]]) {
1629             // For some reason, the Java plug-in requires that we pass the dimension of the plug-in as attributes.
1630             NSMutableArray *names = kit(paramNames);
1631             NSMutableArray *values = kit(paramValues);
1632             if (parameterValue(paramNames, paramValues, "width").isNull()) {
1633                 [names addObject:@"width"];
1634                 [values addObject:[NSString stringWithFormat:@"%d", size.width()]];
1635             }
1636             if (parameterValue(paramNames, paramValues, "height").isNull()) {
1637                 [names addObject:@"height"];
1638                 [values addObject:[NSString stringWithFormat:@"%d", size.height()]];
1639             }
1640             view = pluginView(m_webFrame.get(), (WebPluginPackage *)pluginPackage, names, values, baseURL, kit(element), NO);
1641         } 
1642 #if ENABLE(NETSCAPE_PLUGIN_API)
1643         else if ([pluginPackage isKindOfClass:[WebNetscapePluginPackage class]]) {
1644             view = [[[NETSCAPE_PLUGIN_VIEW alloc] initWithFrame:NSMakeRect(0, 0, size.width(), size.height())
1645                 pluginPackage:(WebNetscapePluginPackage *)pluginPackage
1646                 URL:nil
1647                 baseURL:baseURL
1648                 MIMEType:MIMEType
1649                 attributeKeys:kit(paramNames)
1650                 attributeValues:kit(paramValues)
1651                 loadManually:NO
1652                 element:element] autorelease];
1653         } else {
1654             ASSERT_NOT_REACHED();
1655         }
1656 #endif
1657     }
1658
1659     if (!view) {
1660         NSError *error = [[NSError alloc] _initWithPluginErrorCode:WebKitErrorJavaUnavailable
1661             contentURL:nil
1662             pluginPageURL:nil
1663             pluginName:[pluginPackage name]
1664             MIMEType:MIMEType];
1665         view = [[[WebNullPluginView alloc] initWithFrame:NSMakeRect(0, 0, size.width(), size.height())
1666             error:error DOMElement:kit(element)] autorelease];
1667         [error release];
1668     }
1669
1670     ASSERT(view);
1671     return adoptRef(new PluginWidget(view));
1672
1673     END_BLOCK_OBJC_EXCEPTIONS;
1674     
1675     return adoptRef(new PluginWidget);
1676 #else
1677     return 0;
1678 #endif // ENABLE(MAC_JAVA_BRIDGE)
1679 }
1680
1681 String WebFrameLoaderClient::overrideMediaType() const
1682 {
1683     NSString* overrideType = [getWebView(m_webFrame.get()) mediaStyle];
1684     if (overrideType)
1685         return overrideType;
1686     return String();
1687 }
1688
1689 void WebFrameLoaderClient::documentElementAvailable() {
1690 }
1691
1692 void WebFrameLoaderClient::windowObjectCleared()
1693 {
1694     Frame *frame = core(m_webFrame.get());
1695     ScriptController *script = frame->script();
1696     WebView *webView = getWebView(m_webFrame.get());
1697     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
1698     if (implementations->didClearWindowObjectForFrameFunc) {
1699         CallFrameLoadDelegate(implementations->didClearWindowObjectForFrameFunc, webView, @selector(webView:didClearWindowObject:forFrame:),
1700             script->windowScriptObject(), m_webFrame.get());
1701     } else if (implementations->windowScriptObjectAvailableFunc) {
1702         CallFrameLoadDelegate(implementations->windowScriptObjectAvailableFunc, webView, @selector(webView:windowScriptObjectAvailable:),
1703             script->windowScriptObject());
1704     }
1705
1706     if ([webView scriptDebugDelegate]) {
1707         [m_webFrame.get() _detachScriptDebugger];
1708         [m_webFrame.get() _attachScriptDebugger];
1709     }
1710 }
1711
1712 void WebFrameLoaderClient::registerForIconNotification(bool listen)
1713 {
1714 #if ENABLE(ICONDATABASE)
1715     [[m_webFrame.get() webView] _registerForIconNotification:listen];
1716 #endif
1717 }
1718
1719 void WebFrameLoaderClient::didPerformFirstNavigation() const
1720 {
1721     WebPreferences *preferences = [[m_webFrame.get() webView] preferences];
1722     if ([preferences automaticallyDetectsCacheModel] && [preferences cacheModel] < WebCacheModelDocumentBrowser)
1723         [preferences setCacheModel:WebCacheModelDocumentBrowser];
1724 }
1725
1726 #if ENABLE(MAC_JAVA_BRIDGE)
1727 jobject WebFrameLoaderClient::javaApplet(NSView* view)
1728 {
1729     if ([view respondsToSelector:@selector(webPlugInGetApplet)])
1730         return [view webPlugInGetApplet];
1731
1732     // Compatibility with older versions of Java.
1733     // FIXME: Do we still need this?
1734     if ([view respondsToSelector:@selector(pollForAppletInWindow:)])
1735         return [view pollForAppletInWindow:[[m_webFrame.get() frameView] window]];
1736
1737     return 0;
1738 }
1739 #endif
1740
1741 bool WebFrameLoaderClient::shouldLoadMediaElementURL(const KURL& url) const {
1742     WebView *webView = getWebView(m_webFrame.get());
1743     
1744     if (id policyDelegate = [webView policyDelegate]) {
1745         if ([policyDelegate respondsToSelector:@selector(webView:shouldLoadMediaURL:inFrame:)])
1746             return [policyDelegate webView:webView shouldLoadMediaURL:url inFrame:m_webFrame.get()];
1747     }
1748     return true;
1749 }
1750
1751 @implementation WebFramePolicyListener
1752
1753 + (void)initialize
1754 {
1755     JSC::initializeThreading();
1756 #ifndef BUILDING_ON_TIGER
1757     WebCoreObjCFinalizeOnMainThread(self);
1758 #endif
1759 }
1760
1761 - (id)initWithWebCoreFrame:(Frame*)frame
1762 {
1763     self = [self init];
1764     if (!self)
1765         return nil;
1766     frame->ref();
1767     m_frame = frame;
1768     return self;
1769 }
1770
1771 - (void)invalidate
1772 {
1773     if (m_frame) {
1774         m_frame->deref();
1775         m_frame = 0;
1776     }
1777 }
1778
1779 - (void)dealloc
1780 {
1781     if (WebCoreObjCScheduleDeallocateOnMainThread([WebFramePolicyListener class], self))
1782         return;
1783
1784     if (m_frame)
1785         m_frame->deref();
1786     [super dealloc];
1787 }
1788
1789 - (void)finalize
1790 {
1791     ASSERT_MAIN_THREAD();
1792     if (m_frame)
1793         m_frame->deref();
1794     [super finalize];
1795 }
1796
1797 - (void)receivedPolicyDecision:(PolicyAction)action
1798 {
1799     RefPtr<Frame> frame = adoptRef(m_frame);
1800     m_frame = 0;
1801     if (frame)
1802         static_cast<WebFrameLoaderClient*>(frame->loader()->client())->receivedPolicyDecison(action);
1803 }
1804
1805 - (void)ignore
1806 {
1807     [self receivedPolicyDecision:PolicyIgnore];
1808 }
1809
1810 - (void)download
1811 {
1812     [self receivedPolicyDecision:PolicyDownload];
1813 }
1814
1815 - (void)use
1816 {
1817     [self receivedPolicyDecision:PolicyUse];
1818 }
1819
1820 - (void)continue
1821 {
1822     [self receivedPolicyDecision:PolicyUse];
1823 }
1824
1825 @end