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