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