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