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