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