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