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