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