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