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