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