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