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