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