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