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